http://blog.youkuaiyun.com/winsunxu/article/details/6220290
三.如何修改编译器的默认对齐值
在编码时,可以这样动态修改:
修改默认对齐值,指定新的内存对齐值:#pragma pack(value)
取消指定的内存对齐值,恢复默认对齐值:#pragma pack()
四.如何进行内存地址对齐
对于一个结构体,不但需要对其每个成员变量进行内存地址对齐,还要对结构体本身进行对齐,具体规则为:在假设结构体起始地址为0x0000的情况下,要求各成员变量的起始地址必须是其相应有效对齐值的整数倍,并要求结构体的大小也为该结构体有效对齐值的整数倍。
例子
例一:
struct A
{
int a;
char b;
short c;
};
则该结构体所占的内存字节数sizeof(struct A) = 8;
具体分析如下:
故该结构体及其成员变量的有效对齐值为编译器默认对齐值和其自身对齐值的最小值:
int a 的自身对齐值为4
char b 的自身对齐值为1
short c 的自身对齐值为2
struct A 的自身对齐值为max(4,1,2) = 4
编译器默认对齐值为各成员变量自身对齐值中的最大值,即为4。
故int a 的有效对齐值为min(4,4) = 4
char b 的有效对齐值为min(1,4) = 1
short c 的有效对齐值为min(2,4) = 2;
struct A 的有效对齐值为min(4,4) = 4
假设结构体A从地址空间0x0000开始排放。由上面的计算可知,第一个成员变量int a的有效对齐值为4,所以其存放的地址为0x0000~0x0003,且其起始地址0x0000符合0x0000%4 = 0;第二个成员变量char b的有效对齐值为1,所以其存放地址为0x00004,且其起始地址0x0004符合0x0004%1 = 0;第三个成员变量short c 的有效对齐值为2,所以其存放地址应该为0x0006~0x0007,而其起始地址0x0006也符合0x0006%2 = 0;
最后还要对整个结构体进行内存地址对齐:即要保证整个结构体的大小应该为其有效对齐值的整数倍,而该结构的有效对齐值为4,现在三个成员变量已经占据了0x0000~0x0007共8个字节的内存空间,而8%4 = 0也符合对齐要求,故整个结构体的大小应该为8.
例二
#pargma pack(8)
struct A
{
short a; //有效对齐值为min(2,8) = 2
long b; //有效对齐值为min(4,8) = 4;
};
struct B
{
char c; //有效对齐值为min(1,8) = 1
struct B s; //有效对齐值为min(4,8) = 4
short e; //有效对齐值为min(2,8) = 2
};
#pargma pack()
分别求出sizeof(struct A)和sizeof(struct B)的值。
类似例一可分析:
sizeof(struct A)= 8,sizeof(struct B)= 16