struct 的内存对齐
成员对齐大小概念
成员对齐值
struct类型中, 每个成员相对于整个 struct 类型变量的开始地址而言, 它的偏移量必须是 对齐值的整数倍.
struct 成员对齐值 由两个规则影响:
- [[# 成员默认对齐值]]
- [[#
pragma pack(n)的作用|pragma pack(n)]]
成员最终对齐值为min(成员默认对齐值, n)
推论: 成员对齐大小 总是2的幂次
证明:
- 由于内置类型成员对齐大小都是2的幂次, 并且 `pragma pack (n)` 只能设为2的幂次
- 由于嵌套结构体成员对齐大小 由它内部成员决定 (也是2的幂次), 或由 alignas 控制 (也是2的幂次)
- 因此成员对齐值 总是2的幂次
成员默认对齐值
- 内置类型的默认对齐值: 比如 int 对齐值为 4, double 为 8 , char 为1字节
- 数组类型的默认对齐值: 数组的对齐值 = 数组元素类型的默认对齐值。
- struct 类型的默认对齐值: 参见 [[# struct 对象作为成员时的内存对齐值]]
- 结构体的默认对齐值 = 它所有成员中最大的默认对齐值
- 若由
alignas指定, 则为指定值.
#pragma pack(n) 的作用
n只能设定为 2 的幂次- 一般用于减小对齐值, 使内存布局更紧凑.
- 它将修改 struct 类型 中 成员的对齐值, 使得其成员对齐值变为
min(成员默认对齐值, n)
struct 整体的内存大小
struct 对象作为成员时的内存对齐值
当结构体 a 作为 另一个结构体的 数据成员时, 需要考虑 成员 a 的对齐值
- struct 内存对齐值 影响该成员的起始地址和内存大小
- struct 成员的起始地址 必须是 struct 内存对齐值 的整数倍
- struct 内存占用大小 必须是 struct 内存对齐值 的整数倍
- struct 内存对齐值 由以下事物决定
- 由
alignas直接指定 - 否则为所有[[#成员对齐值]]的最大值
- 由
***推论:***
- struct 对象的内存对齐值 是[[#成员对齐值]]的整数倍
- 若没有指定 `#pragma pack(n)`, 则内存大小是所有[[#成员默认对齐值]] 中最大值 的整数倍
- 如果指定了 `#pragma pack(n)`, 则内存大小必然是 `n` 的整数倍
- 若指定了 `alignas(m)` ,则内存大小必然是 `m` 的整数倍
- 以上两条规则独立地起作用
alignas 规则
作用:
- 用于控制结构体整体的对齐为
m, 它不修饰每个成员的对齐规则. - 设置
alignas(m)后, 结构体的起始地址和总大小必须对齐到m
取值规则:
- 取值
m只能是2的幂次 - 取值
m不能小于 最大的[[#成员对齐值]], 且必须是所有成员对齐值的整数倍- 若没有指定
#pragma pack(n), 则m不能小于 最大的[[#成员默认对齐值]] - 若指定了
#pragma pack(n), 则m不能小于n
- 若没有指定
struct 内存对齐总结和例子
总结
从下面例子中的内存布局图来看
- 结构体内存总是要占据一个完整矩形
#alignas(n)实际上控制了 这个矩形列的大小#pragma pack(n)则控制成员之间的紧密程度

例子
例子1:
struct A { //结构体对齐值 8
double x; // 成员对齐值 8 , offset = 0
int a; // 成员对齐值 4 , offset = 8
char b[1]; // 成员对齐值 1 , offset = 12
int c; // 成员对齐值 4 , offset = 16
};
解释:
- 由于不指定
pack (n), 所有成员的对齐值都是 成员默认对齐值 - 结构体的整体对齐值为 8
- 总结构体大小为24, 内存布局如图

例子2:
struct D { //结构体对齐值 4, 总大小8
int a; // 成员对齐值 4
int b; // 成员对齐值 4
};
struct B { //结构体对齐值 4, 总大小24
D d; //成员对齐值 4 , 大小为 8
int a; //成员对齐值 4
char b[10]; //成员对齐值 1
};
解释:
- 成员
d的默认对齐值为 它的成员最大对齐值, 因此为4 - 整体的 B 的对齐值为4,
- 内存布局如图

例子4
#pragma pack(2)
struct alignas(4) A { // 整体对齐值 4, 总大小 40
double x; // 成员对齐值 2, offset 0
double y; // 成员对齐值 2, offset 8
int a; // 成员对齐值 2, offset 16
char b1[7]; // 成员对齐值 1, offset 20
char b2[7]; // 成员对齐值 1, offset 27
int c; // 成员对齐值2, offset 34
};
解释:
- 成员对齐值= min (2, 成员默认对齐值)
- 结构体总大小为4的倍数
- 最后一个成员结束为34+4=38字节, 但考虑总大小为4的倍数, 因此是40字节
- 布局如下

例子5
struct alignas(64) A { // 整体对齐 64字节 总大小64字节
double x;
int a;
char b1;
char b2;
int c;
};
内存布局如图


浙公网安备 33010602011771号