类或结构体是按照一定的对齐方式存储在内存中的。默认为4字节对齐,可以使用#pragma预编译指令指定对齐字节数。
#pragma pack(4)
typedef struct {
char a;
int b;
short c;
char d;
short e;
} T;
sizeof(T)结果是多少?
#pragma pack(2)
typedef struct {
char a;
int b;
short c;
char d;
short e;
} T;
现在sizof(T)结果又是多少呢?
这里有一个取小原则:成员变量按照#pragma pack()规定的数值和自身长度中比较小那个值对齐。类或结构体按照#pragma pack()规定的数值和最大数据成员的长度中比较小的那个值对齐。下面分析上面两个结构体:
#pragma pack(4)
typedef struct {
char a; //放在(0)位置
int b;//自身长度为4,#pragma pack规定的字节数为4,取小值,即按照4字节对齐,放在(4,7)位置上
short c;//自身长度为2,#pragma pack规定的字节数为4,取小值,即按照2字节对齐,放在(8,9)位置上
char d;//自身长度为1,#pragma pack规定的字节数为4,取小值,即按照1字节对齐,放在(10)位置上
short e;//自身长度为2,#pragma pack规定的字节数为4,取小值,即按照2字节对齐,放在(12,13)位置上
} T;
也就是说,该结构体实际占据了14个字节,数据成员最大长度(int)为4,#pragma pack()规定的字节数为4,取小值,即14按4字节圆整,结构体一共占用了16个字节。
#pragma pack(2)
typedef struct {
char a; //放在(0)位置
int b;//自身长度为4,#pragma pack规定的字节数为2,取小值,即按照2字节对齐,放在(2,5)位置上
short c;//自身长度为2,#pragma pack规定的字节数为2,取小值,即按照2字节对齐,放在(6,7)位置上
char d;//自身长度为1,#pragma pack规定的字节数为2,取小值,即按照1字节对齐,放在(8)位置上
short e;//自身长度为2,#pragma pack规定的字节数为2,取小值,即按照2字节对齐,放在(10,11)位置上
} T;
也就是说,该结构体实际占据了11个字节,数据成员最大长度(int)为4,#pragma pack()规定的字节数为1,取小值,即11按2字节圆整,结构体一共占用了12个字节。
我们可以通过观察内存验证一下上面的分析:
T t;
t.a = 'A';
t.b = 1;
t.c = 2;
t.d = 'B';
t.e = 3;
(1)#pragma pack(4)时,内存中的数据为:
41 CC CC CC 01 00 00 00 02 00 42 CC 03 00 CC CC
(2) #pragma pack(2)时,内存中的数据为:
41 CC 01 00 00 00 02 00 42 CC 03 00
可以发现,与我们的分析完全吻合。C++类的对齐方式和C结构体完全相同,只要把struct改为class就可以了,有兴趣大家可以验证一下。以上观点如果有误,欢迎大家批评指正!