sizeof是计算变量、指针、数组、结构体、联合体等数据类型或对象(c++)所占内存的大小。
变量、指针较容易。数组sizeof计算时,注意字符型的数组包括末尾的结束符'\0',因为也占用了内存空间。
char * p[10]="1234";
sizeof(p)=10
分配的字符串空间为10.
strlen是计算数组中已经用了的空间长度。
strlen(p)=4
1、结构体
结构体牵涉到字节对齐。字节对齐的细节和编译器实现相关,但一般而言,满足三个准则:
1) 结构体变量的首地址能够被其最宽基本类型成员的大小所整除;
2) 结构体每个成员相对于结构体首地址的偏移量(offset)都是成员大小的整数倍,如有需要编译器会在成员之间加上填充字节(internal adding);
3) 结构体的总大小为结构体最宽基本类型成员大小的整数倍,如有需要编译器会再最末一个成员之后加上填充字节(trailing padding)。
根据以上规则,在vc6.0中实验如下:
struct S1{
int a;
char b;
}S1;
struct S3{
char a;
struct S1 s;
char b;
}S3;
struct S4{
struct S1 s;
char a;
char b;
}S4;
struct S2{
char a;
char b;
char c;
}S2;
struct S5{
char a;
}S5;
结果:sizeof(S1)=8 sizeof(S3)=16 sizeof(S4)=12 (结构体成员变量定义位置变化,字节填充不同导致的)
sizeof(S2)=3 (而不是4) sizeof(S5)=1 (而不是4)
2、联合体
struct ch1{
char a:4;
char b:4;
};
union ss
{
struct ch1 a;
char b;
char c;
};
sizeof(ch1)=1 sizeof(ss)=1
联合体取其每个成员sizeof的最大值。这里struct ch1字节对齐后仍为1.
3、含有位域的结构体
位域的引入是为了压缩存储。编译器对数据类型的扩展就有了位域。 其大致规则:
1)如果相邻位域字段的类型相同,且其位宽之后小于类型的sizeof大小,则后面的字段将紧邻前一个字段存储,直到不能容纳为止;
2)如果相邻位域字段的类型相同,但其位宽之和大于类型的sizeof大小,则后面的字段将从新的存储单元开始,其偏移量为类型大小的整数倍;
例如:
struct BF1{
char f1:3;
char f2:4;
char f3: 5;
};
f1、f2在第1个字节(占7位,最后一位空着);
f3从第2字节开始分配(占前5位)。
sizeof(BF1)=2
struct BF2{
char f1:3;
short f2:4;
char f3:5;
};
在vc中,不进行压缩存储,所以sizeof(BF2)=6
在Dev-C++中,仍进行压缩存储,所以sizeof(BF2)=2
3)如果相邻的位域字段类型不同,则个编译器的具体实现有差异,VC6采取不压缩方式,Dev-C++采取压缩方式;
4)如果位域字段之间穿插着非位域字段,则不进行压缩;
5)整个结构体的总大小为最宽基本类型成员大小的整数倍。