众所周知,程序为了提高访问效率,编译器在编译的时候,进行字节对齐。程序员也可以字节指定对齐方式。
Win32下的为progma指令,具体来说
#pragma pack(push) //保存原对齐状态
#pragma pack(4)//设定为4字节对齐
struct test
{
int a;
};
#pragma pack(pop)//恢复对齐状态
在linux下,gcc是默认的编译器。g++ 支持progma指令,gcc也支持GNU扩展__attribute__指令
参考《__attribute__》,对于字节对齐的举例为
struct test{
short b[3];
} __attribute__ ((aligned (8)));
__attribute__还支持aligned 和 packed ,解释如下
__attribute__ ((aligned)); 选择针对目标机器最大的对齐方式,可以提高拷贝操作的效率。aligned属性使被设置的对象占用更多的空间,相反的,使用packed可以减小对象占用的空间。需要注意的是,attribute属性的效力与你的连接器也有关,如果你的连接器最大只支持16字节对齐,那么你此时定义32字节对齐也是无济于事的。
__attribute__ ((packed))使用该属性可以使得变量或者结构体成员使用最小的对齐方式,即对变量是一字节对齐,对域(field)是位对齐。
下面以pragma 来讨论指定结构体对齐方式!
总的来说规律如下
#pragma pack(n)来设定变量以n字节对齐方式。n字节对齐就是说变量存放的起始地址的偏移量有两种情况:
第一、如果n大于等于该变量所占用的字节数,那么偏 移量必须满足默认的对齐方式
第二、如果n小于该变量的类型所占用的字节数,那么偏移量为n的倍数,不用满足默认的对齐方式。
结构的总大小也有个约束条 件,分下面两种情况:
如果n大于所有成员变量类型所占用的字节数,那么结构的总大小必须为占用空间最大的变量占用的空间数的倍数;
否则必须为n的倍数。alignment (n) must be a small power of two
示例
struct test
{
char m1;
double m4;
int m3;
};
如果不指定对齐方式的话,其以double所占空间大小对齐,即
sizeof(struct test) = 24 (IA32 GCC)
此处让我想起linux中的container_of,和offset宏。