对齐规则
在没有#pragma pack宏的情况下:
1.数据成员对齐规则:struct, union的数据成员,第一个数据成员放在offset为0的地方,之后的数据成员的存储起始位置都是放在该数据成员大小的整数倍位置。如在32bit的机器上,int的大小为4,因此int存储的位置都是4的整数倍的位置开始存储。
2.结构体作为数据成员的对齐规则:在一个struct中包含另一个struct,内部struct应该以它的最大数据成员大小的整数倍开始存储。如 struct A 中包含 struct B, struct B 中包含数据成员 char, int, double,则 struct B 应该以sizeof(double)=8的整数倍为起始地址。
3.收尾工作的对齐规则:整个struct的大小,应该为最大数据成员大小的整数倍。
实例演示
假设在64位机器下
class test1 {
int a; //内存位置:[0]..[3]
char b; //内存位置:[4]
int* c; //内存位置:[8]..[15]
}
sizeof(test1) = 16
class test2 {
short x; //内存位置:[0]..[1]
double y; //内存位置:[8]..[15]
test1 t; //内存为止:[16]..[32]
char z; //内存为止:[17]
}
sizeof(test2) = 2 + (6) + 8 + 16 + 1 + (7) = 40
64位与32位
c++中数据类型的长度并不是简单根据机器字长确定的。其实还是由编译器决定的,所以在很多64位机器上int仍然是32位字长。所以很多时候要根据具体情况具体分析,更多情况下两者的基础数据类型是等长的。
指针比较特殊,指针是用于寻址的,64位下都是64位,而32位下为32位。指针的大小应该是和操作系统字长统一了的。所以在上面的例子中,64位机器下int*的大小是8字节,如果是32位下就应该是4字节。
pragma pack
宏pragma pack可以屏蔽掉编译器默认的对齐方式,而自己设定对齐大小。
在上面的例子中,如果加上这个宏将会是如下的情况:
#pragma pack(1)
//以1字节对齐
//sizeof(test1) = 13
//sizeof(test2) = 24
#pragma pack(2)
//以2字节对齐
//sizeof(test1) = 14
//sizeof(test2) = 26