一、为什么需要自己对齐?
1.CPU对内存的读取不是连续的,是分成块读取的,块的大小只能是1、2、4、8、16…字节。
2.当读取操作的数据未对齐,则需要两次总线周期来访问内存,因此程序性能会降低。
比如某一个int型数据其实位置在内存的0x00000002位置,则没有按4字节对齐。要读取他的值的话需要访问两次内存,第一次取从0x00000002-0x00000003的一个short,第二次取从0x00000004-0x00000005的一个short然后组合得到int。
3.某些硬件平台只能从规定的相对地址读取特定的数据,否则产生硬件异常。
二、编译器字节对齐方式
1.一般情况下32位操作系统默认按4字节对齐,64位操作系统按8字节对齐。
2.#pragma pack(n)
:编译器将按照n个字节对齐。
3.#pragma pack()
:取消自定义字节对齐方式。
三、字节对齐规则
struct占用的内存大小:
1.第一个成员默认是自己对齐的,即在0偏移处。
2.每个成员的对齐参数采用:类型大小和默认对齐参数中较小的一个对齐。
3.每个成员的偏移地址必须能被对齐参数整除。
4.若成员为结构体其对齐参数取其内部长度最大的数据成员作为对齐参数。
5.结构体总长度必须为所有对齐参数的整数倍。
四、示例
请看下面示例:
struct Test1
{ // 对齐参数 偏移地址 大小
char c1; // 1 0 1
short s; // 2 2 2
char c2; // 1 4 1
int i; // 4 8 4
};
sizeof(struct Test1) = 12
struct Test2
{ // 对齐参数 偏移地址 大小
char c1; // 1 0 1
char c2; // 1 1 1
short s; // 2 2 2
int i; // 4 4 4
};
sizeof(struct Test1) = 8
struct S1
{ // 对齐参数 偏移地址 大小
short a; // 2 0 2
long b; // 4 4 4
};
struct S2
{ // 对齐参数 偏移地址 大小
char c; // 1 0 1
shtruct S1 d; // 4 4 8
double e; // 4 12 8
};
sizeof(struct S1) = 8;
sizeof(struct S2) = 20;