最开始学习结构体对齐的时候 ,总是不明白到底什么是结构体对齐,说的4字节对齐感觉有些概念模糊
我们可以添加预编译指令#pragma pack(n)来改变对齐方式(我们目前只讨论x86下的对齐方式)
我们先看一个没有添加预编译指令的例子
struct s1
{
short a;
long b;
};
struct s2
{
char c;
s1 d;
long long e;
};
输出结果:sizeof(s1)=8 sizeof(s2)=24
根据我测试的结论:
在没有添加预编译指令的情况下,
所谓的结构体对齐是指结构体,成员在内存中的地址减去结构体在内存中的地址的结构一定是成员类型大小的倍数
比如结构体首地址为a , 则int型成员相对于a的偏移offset(int)一定为4的倍数 ,
offset(double)一定为8的倍数
我们假设s2的地址为p,则相应成员的地址为:
s2.c->p
s2.d.a.->p+8
s2.d.b->p+12
s2.e->p+16
但是如果加了#pragma pack(n)指令就会改变结构体成员的对齐方式
那么又会以什么样的规则对齐了,经过我的几次测试发现:
结构体成员地址偏移要取决于成员类型大小和#pragma pack中的较小值
比如说int型字节数为4 ,加入#pragma pack(1) ,1<4-->则int型成员的偏移为1(如果没加预编译指令应该是4的)
再比如long long 型字节数为8 ,加入#pragma pack(4) 4--> 则long long型成员偏移为4(如果没加预编译指令应该是8的)
假设我们以#pragma pack(1)来对齐,看下面这个例子
我们假设s2的地址为p,则相应成员的地址为:
s2.c->p
s2.d.a.->p+1
s2.d.b->p+3
s2.e->p+7
我们改下#pragma pack(4)
我们假设s2的地址为p,则相应成员的地址为:
s2.c->p
s2.d.a.->p+4
s2.d.b->p+8
s2.e->p+12