一、Sizeof的说明
sizeof是C/C++语言的一种单目操作符,它不是函数。sizeof操作符返回值为其操作数的存储大小,用字节数表示。操作数可以是一个表达式或括在括号内的类型名。 sizeof的结果是size_t,它被定义为unsigned int类型。该类型保证容纳显示所建立的最大对象的字节大小。
- static变量在静态区,sizeof均不纳入计算
- 在编译阶段处理,sizeof作用范围内的内容不能被编译,所以sizeof()内的运算不被执行
- sizeof(函数)=sizeof(返回值类型)
- sizeof和strlen:sizeof计算字符串容量,算’\0’,strlen计算字符串长度,到’\0’截止
- 类:非static数据成员变量+虚函数指针+对齐;无论多少个虚函数,都只有一个指向虚函数表的指针(4字节)
- 联合体:最长成员的大小对齐
- 带位域:相邻位域字段的两个变量若类型相同,当两个字段位宽和小于此类型大小时,二者紧邻存储;若二者位宽和大于本类型大小,则第二个字段从新存储单元开始,偏移量为其类型大小整数倍。若相邻位域字段类型不同,则视编译器决定是否压缩存储,VC6不压缩,Dec-C++压缩。如果位域字段间穿插着非位域字段,不压缩。
- 数组:数组占内存字节=元素个数*元素长度; 当数组作为函数参数传递时,蜕变成指针
需牢记sizeof的计算发生在编译时刻,所以它可以被当作常量表达式使用,且会忽略其括号内的各种运算。
二、Sizeof的使用
1、sizeof的使用形式:sizeof(var_name)或者sizeof var_name
2、数据类型必须用括号括起来:sizeof(type)
变量、对象可以不用括号括住:sizeof a,但若是类型必须用括号。
3、sizeof可以对表达式求值:sizeof(2.5+3.14),实际是sizeof(double)
4、sizeof可以对函数调用求值,实际上是对返回值类型求值
int func(char s[5]);
{
cout<<endl;
return 1;
}
sizeof(func(“1234”))=4 //因为func的返回类型为int,所以相当于求sizeof(int)=4,sizeof(s)=4
5、以下情况不能用sizeof进行求值
1)不能对函数名求值
2)不能对不确定返回值的类型求值,如void
3)位域成员不可以使用sizeof求值
4)不完全类型或位字段。不完全类型指具有未知存储大小的数据类型,如未知存储大小的数组类型、未知内容的结构或联合类型、void类型等。
一般,在32位编译器下:
sizeof(char):1
sizeof(short):2
sizeof(int):4
sizeof(long):4
sizeof(float):4
sizeof(double):8
sizeof(long long):8
sizeof(p):4,(p为指针)
32位系统下指针的sizeof是4字节,64位下是8字节
6.指针与静态数组的sizeof操作
1) 指针均可看为变量类型的一种。所有指针变量的sizeof 操作结果均为4。
注意: int *p; sizeof(p)=4;(32位系统下始终不变)sizeof(*p)相当于sizeof(int),随着数据类型的改变而改变;
2) 对于静态数组,sizeof可直接计算数组大小;当数组动态分配时,int *a = new int[10]; sizeof = 4。
例: int a[10];char b[]="hello";
sizeof(a)等于4*10=40;
sizeof(b)等于6;
注意:数组做形参时,数组名称当作指针使用!!
void fun(char p[]) {sizeof(p)等于4}
如下程序:
#include <stdio.h>
void func(char p[])
{
printf("in func args,p[] size %d\n", sizeof(p));
}
int main()
{
int *p;
int a[10];
char b[] = "hello";
printf("*p size %d\n", sizeof(p));
printf("a[10] size %d\n", sizeof(a));
printf("\"hello\" size %d\n", sizeof(b));
func(b);
return 0;
}
输出结果:*p size 4
a[10] size 40
"hello" size 6
in func args,p[] size 4
经典问题:
//double* (*a)[3][6];
#include <stdio.h>
int main()
{
double *(*a)[3][6];
printf(" a size %4d\n",sizeof( a));// 4 a为指针
printf(" *a size %4d\n",sizeof( *a));// 72 *a为一个有3*6个指针元素的数组
printf(" **a size %4d\n",sizeof( **a));// 24 **a为数组一维的6个指针
printf(" ***a size %4d\n",sizeof( ***a));// 4 ***a为一维的第一个指针
printf("****a size %4d\n",sizeof(****a));// 8 ****a为一个double变量
return 0;
}
问题解析:
- a是一个很奇怪的定义,他表示一个指向 double*[3][6]类型数组的指针。既然是指针,所以sizeof(a)就是4。
- *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。
7、sizeof与strlen()比较,在计算字符数组大小时,sizeof包含'\0',strlen()不包含'\0',strlen()遇到’\0’就会返回
char c1[ ]={‘c’,‘ ’,‘p’,‘r’,‘o','g','r','a','m'};
char c2[ ]={‘c’,‘ ’,‘p’,‘r’,‘o','g','r','a','m','\0'};
strlen(c1)未定义,strlen(c2)=9;
sizeof(c1)=9,sizeof(c2)=10
注意,sizeof("\0")=2
8、对引用的sizeof,其实是对其所绑定的对象的sizeof
9、对于C字符串,需要牢记C/C++中一个汉字占两个字节(Linux下3个字节),且字符串尾有空字符。
使用伪指令#pragma pack(n),编译器将按照n个字节对齐;
使用伪指令#pragma pack(n),将取消自定字节对齐方式。
10、 sizeof的参数为结构或类时,有两点需要注意:
第一、结构或者类中的静态成员不对结构或者类的大小产生影响,因为静态变量的存储位置与结构或者类的实例地址无关。
第二、没有成员变量的结构或类的大小为1,因为必须保证结构或类的每一个实例在内存中都有唯一的地址。
还有结构体或者类中有虚函数的,大小会加4个字节,因为有虚函数表的指针。
Class Test{int a;static doublec};//sizeof(Test)=4.
Test *s;//sizeof(s)=4,s为一个指针。
Class test1{ };//sizeof(test1)=1;