背景
cpu读取内存是以2的整数次幂为单位读取(一次读取一块内存,如一次读入4个字节),如果不进行对齐,那么本来只需要一次进行的访问,可能需要好几次才能完成,并且还要进行额外的merger或者数据分离。
方法
- 先确定实际对齐单位,其由以下三个因素决定
-
结构体最大成员(基本数据类型变量)
-
预编译指令#pragma pack(n)手动设置 n–只能填1、2、4、8、16
-
CPU周期
- WIN vs qt 默认8字节对齐
- Linux 32位 默认4字节对齐,64位默认8字节对齐
上面三者取最小的,就是实际对齐单位(这里的“实际对齐单位”是我为了方便区分随便取的概念)
-
除结构体的第一个成员外,其他所有的成员的地址相对于结构体地址(即它首个成员的地址)的偏移量必须为实际对齐单位或自身大小的整数倍(取两者中小的那个)
-
结构体的整体大小必须为实际对齐单位的整数倍。
-
嵌套结构体的实际对齐单位是自己内部成员的对齐数中的最大对齐数。
例子
x86_64环境
设结构体如下定义:
struct A
{
int a;
char b;
short c;
};
struct B
{
char b;
int a;
short c;
};
对于结构体A:
- 实际对齐单位为4(最大成员变量)
- a的偏移量为0
- b的偏移量为4
- c的偏移量为6
0 --- a
1 --- a
2 --- a
3 --- a
4 --- b
5 --- buff
6 --- c
7 --- c
总大小为8
对于结构体B:
- 实际对齐单位为4
0 --- b
1 --- buff
2 --- buff
3 --- buff
4 --- a
5 --- a
6 --- a
7 --- a
8 --- c
9 --- c
10 -- buff
11 -- buff
总大小为12