C++关键字之——sizeof运算符
目录
2.sizeof怎么用?
- 基本内置类型
- 复合类型
- 类
3.sizeof与strlen()?
4.sizeof用途?
1.sizeof 是什么?
sizeof 是一种一元运算符!它返回一个表达式(expr)或一个类型名字所占的字节数。形如sizeof(expr)(括号可以省去),sizeof(type)。sizeof的结果类型是size_t,被定义为unsigned int类型。
2.sizeof怎么用?
其实很简单,上面已经谈到sizeof运算符的两种对象形式,表达式和类型名字。
-
基本内置类型
对于类型名字而言如C++内置类型名字bool,char,short,int ,long,long long, float,double ,long double,通过Visual Studio如下程序:
#include<iostream>
using namespace std;
int main(void)
{
cout << "sizeof(bool):"<<sizeof(bool) << endl; //1
cout << "sizeof(char):"<<sizeof(char) << endl; //1
//扩展字符集之一:wchar_t宽字符 2
cout << "sizeof(wchar_t):" << sizeof(wchar_t) << endl;//
//扩展字符集之二:Unicode字符集char16_t 2
cout << "sizeof(char16_t):"<<sizeof(char16_t) << endl;
扩展字符集之三:Unicode字符集char32_t 4
cout << "sizeof(char32_t):"<<sizeof(char32_t) << endl;
cout << "sizeof(short):" << sizeof(short) << endl; //2
cout << "sizeof(int):" << sizeof(int) << endl; //4
cout << "sizeof(long):" << sizeof(long) << endl; //4
cout << "sizeof(long long):" <<sizeof(long long) << endl;//8
cout << "sizeof(float):" << sizeof(float) << endl; //4
cout << "sizeof(double):" << sizeof(double) << endl; //8
cout << "sizeof(long double):" << sizeof(long double) << endl;//8
return 0;
}
以上截图就是C++所有的内置类型在Visual Studio上运行的结果,其中扩展字符集wchar_t,char16_t,char32_t用的比较少,然而在GCC32 上运行sizeof(long double)=12;而GCC64上sizeof(long double)=16.
-
复合类型
复合类型主要有指针,引用,以及STL中vector, string等。当定义一个指针(char *p),尤其要注意sizeof(p),此时是计算指针所占的空间大小,结果为4,所有指针所占用空间大小都为4个字节,不论其指向什么类型的对象,而sizeof(*p),则是指向指针所指向对象空间大小1。原因有二:
sizeof运算符满足右结合律,并且与*sizeof运算符的优先级一致;
sizeof不会真正求运算对象的值,即使p是一个无效的指针,在sizeof运算符中,解引用一个无效的指针仍然是一种安全的行为,因为指针并没有被真正使用。《C++ Primer》
sizeof运算符的结果部分依赖于其作用的类型
- 对内置基本类型或其类型的表达式使用sizeof运算符,如int a,b;sizeof(int ) sizeof (a+b),其结果都为其对内置类型取sizeof运算符所得结果;
- 对引用类型或解引用指针使用sizeof 运算符,所得结果是引用或指针所指向对象所占空间的大小;
- sizeof一个指针,得到的是指针本身所占空间大小,32位系统下4B,而64位系统下8B;
- sizeof一个数组,则得到是整个数组所占空间的大小,等价于对数组中每个元素执行一次sizeof求和。Notice:sizeof不会把数组转换为指针处理,除非数组首元素作为函数形参传递,此时数组退化为指针。
- 对vector对象或string对象执行sizeof运算只会返回该类型固定部分的大小,不会计算对象中元素占用多少空间。
对于第4,5两条,通过如下代码和结果一目了然!
#include<iostream>
#include<vector>
#include<string>
using namespace std;
void fun(int a[])
{
//数组作为函数形参,数组退化为指针
cout << "sizeof(a)="<<sizeof(a) << endl;
}
int main(void)
{
vector<int>vec;
string str;
cout << "sizeof(vec)="<<sizeof(vec) << endl;
cout << "sizeof(str)="<<sizeof(str) << endl;
int a[4] = {0,1,2,3};
fun(a); //
cout << "sizeof(a)=" << sizeof(a) << endl;
return 0;
}
-
类
对于类,尤其要注意一个空类,一个带有虚函数的类。
#include<iostream>
using namespace std;
class Empty //空类
{
};
class vEmpty //有虚函数的类
{
vEmpty() {}
virtual int f() {}
~vEmpty() {}
};
int main(void)
{
cout << "sizeof(Empty)="<<sizeof(Empty) << endl;
cout << "sizeof(vEmpty)=" << sizeof(vEmpty) << endl;
return 0;
}
结果:
sizeof(Empty)=1
sizeof(vEmpty)=4
- 对于一个空类,无任何成员变量和成员函数,不包含任何信息,按理来说求sizeof应该为0,但是当我们声明该类型的实例,它必须在内存空间占有一定的空间,否则无法使用这些实例。编译器指定,在Visual Studio中,每个空类实例占用一个字节。
- 若空类中拥有构造函数和析构函数,结果仍为1。调用构造函数和析构函数只需要知道函数的入口地址即可,而这些函数的地址只与类型相关,与类型的实例无关,编译器不会因为函数而在实例内添加任何额外的信息。
- 而对于拥有虚函数的类,在C++中,编译器一旦发现虚函数,就会为该类型生成一个虚函数表,并在该类型每个实例中添加一个指向虚函数表的指针。
对于类中或结构体,执行sizeof,由于涉及到结构体内存对齐,今后会专门写一篇博客关于结构体内存对齐!
3.sizeof与strlen()
-
sizeof是运算符,而strlen()为C语言库函数;
-
sizeof在编译期间,计算的是类型或表达式对象的所占内存空间的大小,而stren()在运行期,计算的是字符串的长度(遇到‘\0’)结束。
4.sizeof用途
为什么需要sizeof呢?计算类型或者表达式对象在内存空间的大小,如果每次都需要程序员通过程序计算,那将是一个很繁琐的工程,一是为了方便,二是为了安全。(我自己想的,嘻嘻!),。对于sizeof的用途,除了上述介绍的,还有
-
sizeof一个主要用途是与存储分配和I/O系统那样的例程进行通信;
-
便于动态分配一些对象,可以让系统知道要分配多少内存,如:int *p=(int*)malloc(sizeof(int));
-
便于一些类型的扩充。在Windows中有很多结构体类型就有一个专用的字段用来存放该类型的字节大小;
-
操作对象的字节数在实现时可能变化,涉及操作对象字节大小是用sizeof代替常量计算。