对齐
对齐 (Alignment) 是对象在存储中摆放位置的约束条件。它直接影响:
- 某个类型的对象能放在哪些地址上;
- 结构体的布局与填充;
- 某些“指针强转 + 解引用”是否会触发未定义行为 (Undefined Behavior, UB)。
1. 对齐要求是什么
对一个类型 T 而言,它有一个对齐要求 (Alignment requirement)。直观理解:
T类型对象的起始地址必须是某个整数倍(通常是alignof(T)的倍数)。
如果一个对象的地址不满足其对齐要求,那么通过该类型的左值访问它,行为通常是 UB。
2. 对齐与结构体布局
结构体的每个成员都有自己的对齐要求。为了让每个成员都能出现在满足对齐要求的位置,编译器可能在成员之间插入填充字节 (Padding),并可能在结构体末尾追加尾部填充,从而使数组元素也满足对齐。
示例(只用于说明,不绑定具体数值):假设 int 需要 4 字节对齐,那么:
c
struct s {
char c;
int n;
};1
2
3
4
2
3
4
n 往往不会紧跟在 c 后面,而是会向后对齐到 4 的倍数地址。
3. 相关工具
- 查询对齐要求:
alignof(T)(见 9.2.2 alignof)。 - 指定更严格的对齐:
alignas(...)(见 9.4.5 alignas)。
4. 习题
- 写一个程序,输出以下类型的
sizeof与alignof:char、short、int、long、long long、double。 - 写一个程序,对比两个结构体:
struct { char c; int n; }struct { int n; char c; }输出它们的sizeof、alignof、成员offsetof,解释差异来自哪里。
- 阅读并判断:以下代码是否一定正确?如果不一定,请解释理由(从“对齐要求”角度回答)。
c
unsigned char buf[sizeof(int)];
int* p = (int*)buf;
*p = 1;1
2
3
2
3