sizeof是一个运算符,计算一个对象在内存中的长度。
sizeof("abc")=4(不是3)
cout < <sizeof("abc") < <endl;
abc被当作常量,传入的是指针,返回4
char *sz[20];//4*20
cout<<sizeof(sz)<<endl;
输出:
80
提示
C中对int型所占的字节长度并没有明确规定,只有一个最大值和最小值,所以具体实现与编译器有关,比如TC中int占两个字节,而VC中占4个字节。但是指针由于表示内存的地址,因此取决于机器的字长,即存储器地址的位数,所以普通的32位机器自然就是占4个字节了
二、由几个例子说开去。
第一个例子:
char* ss = "0123456789"; sizeof(ss) 结果 4 ===》ss是指向字符串常量的字符指针 sizeof(*ss) 结果 1 ===》*ss是第一个字符 char ss[] = "0123456789"; sizeof(ss) 结果 11 ===》ss是数组,计算到/0位置,因此是10+1 sizeof(*ss) 结果 1 ===》*ss是第一个字符 char ss[100] = "0123456789"; sizeof(ss) 结果是100 ===》ss表示在内存中的大小 100×1 strlen(ss) 结果是10 ===》strlen是个函数内部实现是用一个循环计算到/0为止之前 int ss[100] = "0123456789"; sizeof(ss) 结果 400 ===》ss表示再内存中的大小 100×4 strlen(ss) 错误 ===》strlen的参数只能是char* 且必须是以''/0''结尾的 char q[]="abc"; char p[]="a/n"; sizeof(q),sizeof(p),strlen(q),strlen(p); 结果是 4 3 3 2
第二个例子:
class X { int i; int j; char k; }; X x; cout<<sizeof(X)<<endl; 结果 12 ===》内存补齐 cout<<sizeof(x)<<endl; 结果 12 同上
第三个例子:
char szPath[MAX_PATH]
如果在函数内这样定义,那么sizeof(szPath)将会是MAX_PATH,但是将szPath作为虚参声明时(void fun(char szPath[MAX_PATH])),sizeof(szPath)却会是4(指针大小)
三、sizeof深入理解。
- 4.数组做sizeof的参数不退化,传递给strlen就退化为指针了。
- 9.数组作为参数传给函数时传的是指针而不是数组,传递的是数组的首地址,如:
fun(char [8]) fun(char [])
都等价于fun(char *)在C++里传递数组永远都是传递指向数组首元素的指针,编译器不知道数组的大小如果想在函数内知道数组的大小, 需要这样做:进入函数后用memcpy拷贝出来,长度由另一个形参传进去fun(unsiged char *p1, int len) { unsigned char* buf = new unsigned char[len+1] memcpy(buf, p1, len); }
有关内容见: C++ PRIMER? - 10.计算结构变量的大小就必须讨论数据对齐问题。为了CPU存取的速度最快(这同CPU取数操作有关,详细的介绍可以参考一些计算机原理方面的书),C++在处理数据时经常把结构变量中的成员的大小按照4或8的倍数计算,这就叫数据对齐(data alignment)。这样做可能会浪费一些内存,但理论上速度快了。当然这样的设置会在读写一些别的应用程序生成的数据文件或交换数据时带来不便。MS VC++中的对齐设定,有时候sizeof得到的与实际不等。一般在VC++中加上#pragma pack(n)的设定即可.或者如果要按字节存储,而不进行数据对齐,可以在Options对话框中修改Advanced compiler页中的Data alignment为按字节对齐。
- int f1(){return 0;};
double f2(){return 0.0;}
void f3(){}
cout<<sizeof(f3())<<endl; // 错误!无法对void类型使用sizeof
cout<<sizeof(f1)<<endl; // 错误!无法对函数指针使用sizeof
cout<<sizeof*f2<<endl; // *f2,和f2()等价,因为可以看作object,所以括号不是必要的。被认为是double
这里有个陷阱,看下面的程序:
int a = 0; cout<<sizeof(a=3)<<endl; cout<<a<<endl; |
输出为什么是4,0而不是期望中的4,3???就在于sizeof在编译阶段处理的特性。由于sizeof不能被编译成机器码,所以sizeof作用范围内,也就是()里面的内容也不能被编译,而是被替换成类型。=操作符返回左操作数的类型,所以a=3相当于int,而代码也被替换为:
int a = 0; cout<<4<<endl; cout<<a<<endl; |
所以,sizeof是不可能支持链式表达式的,这也是和一元操作符不一样的地方。
结论:不要把sizeof当成函数,也不要看作一元操作符,把他当成一个特殊的编译预处理。
这里有一个陷阱:
int *d = new int[10]; cout<<sizeof(d)<<endl; // 4 |
d是我们常说的动态数组,但是他实质上还是一个指针,所以sizeof(d)的值是4。
再考虑下面的问题:
double* (*a)[3][6]; cout<<sizeof(a)<<endl; // 4 cout<<sizeof(*a)<<endl; // 72 cout<<sizeof(**a)<<endl; // 24 cout<<sizeof(***a)<<endl; // 4 cout<<sizeof(****a)<<endl; // 8 |
a是一个很奇怪的定义,他表示一个指向 double*[3][6]类型数组的指针。既然是指针,所以sizeof(a)就是4。
既然a是执行double*[3][6]类型的指针,*a就表示一个double*[3][6]的多维数组类型,因此sizeof(*a)=3*6*sizeof(double*)=72。同样的,**a表示一个double*[6]类型的数组,所以sizeof(**a)=6*sizeof(double*)=24。***a就表示其中的一个元素,也就是double*了,所以sizeof(***a)=4。至于****a,就是一个double了,所以sizeof(****a)=sizeof(double)=8。