C语言中的结构体对齐(Struct Alignment)是为了提高 CPU 访问内存的效率,编译器会按照一定的规则在结构体成员之间插入“填充字节(padding)”,使得每个成员的地址满足其对齐要求(alignment requirement) 。
一、基本概念
-
对齐要求(Alignment Requirement) :通常等于该类型在当前平台上的大小(但不总是)。例如:
char:1 字节,对齐要求为 1short:2 字节,对齐要求为 2int:4 字节,对齐要求为 4double:8 字节,对齐要求为 8(在某些 32 位系统上可能是 4)- 指针:通常是 4(32 位)或 8(64 位)
-
结构体总大小:必须是其最大成员对齐要求的整数倍(即整体对齐)。
二、对齐规则(以默认对齐方式为例)
- 第一个成员从偏移 0 开始。
- 后续每个成员的起始偏移必须是其自身对齐要求的整数倍。如果当前偏移不满足,则在前面填充字节。
- 整个结构体的大小必须是结构体中最大对齐要求的整数倍。如有必要,在末尾填充。
三、示例分析
示例 1:
struct A {
char a; // 1 字节
int b; // 4 字节
short c; // 2 字节
};
分析:
a从偏移 0 开始,占 1 字节 → 下一个可用偏移 = 1b要求 4 字节对齐 → 下一个 4 的倍数是 4 → 在 1~3 插入 3 字节 paddingb占 4 字节(偏移 4~7)→ 下一个可用偏移 = 8c要求 2 字节对齐 → 8 是 2 的倍数 → 直接放(偏移 8~9)- 当前大小 = 10 字节
- 最大对齐 = max(1,4,2) = 4
- 总大小必须是 4 的倍数 → 向上对齐到 12
✅ sizeof(struct A) = 12
示例 2(优化顺序减少 padding):
struct B {
int b; // 4
short c; // 2
char a; // 1
};
b:偏移 0~3c:偏移 4~5(4 是 2 的倍数)a:偏移 6(1 对齐任意地址)- 当前大小 = 7
- 最大对齐 = 4 → 总大小需为 4 的倍数 → 补到 8
✅ sizeof(struct B) = 8(更节省空间!)
四、如何查看/控制对齐?
1. 查看对齐值(C11 起支持):
#include <stdalign.h>
printf("%zu\n", alignof(int)); // 输出 int 的对齐要求
2. 使用编译器指令控制对齐:
-
GCC / Clang:
struct __attribute__((packed)) S { ... }; // 禁用对齐(可能影响性能) struct __attribute__((aligned(8))) S { ... }; // 强制按 8 字节对齐 -
MSVC:
#pragma pack(push, 1) // 1 字节对齐 struct S { ... }; #pragma pack(pop)
⚠️ 注意:强制取消对齐(如 packed)可能导致 CPU 访问未对齐数据而变慢,甚至在某些架构(如 ARM)上引发异常。
五、总结口诀
“各就各位,对齐先行;整体补齐,最大为尊。”