alignof 返回编译期类型对齐值(std::size_t),如 alignof(int*) 在 x86-64 下恒为 8;alignas 用于声明时强制提升对齐(必须是 2 的幂),需配合 aligned_alloc 或对齐版 operator new 动态分配。

alignof 用来查类型对齐要求,不是运行时值
alignof 是编译期运算符,返回 std::size_t,表示某类型在当前平台上的自然对齐字节数。它不看变量实际地址,只看类型定义本身。
常见误区是以为 alignof(int*) 会因指针值不同而变——不会,它只取决于目标平台的 ABI(比如 x86-64 下通常为 8)。
-
alignof(char)恒为 1,因为char是最小寻址单位 -
alignof(double)在多数 64 位系统上为 8,但嵌入式平台可能为 4 - 对结构体,
alignof取其最大成员对齐值(除非有alignas显式覆盖) - 注意:数组类型如
alignof(int[3])和alignof(int)相同,对齐由元素决定,不是整个数组大小
alignas 控制变量或类型的对齐边界,必须是 2 的幂且 ≤ 实现支持上限
alignas 是声明说明符,用于强制提升对齐要求。它不能降低对齐(比如对 int 写 alignas(1) 无效),只能设为更大、且是 2 的整数次幂(如 1/2/4/8/16/…)。
典型用法是配合 SIMD 或硬件寄存器访问,例如 AVX2 要求 32 字节对齐:
立即学习“C++免费学习笔记(深入)”;
alignas(32) float data[8]; // 确保 data 起始地址 % 32 == 0
struct alignas(64) cache_line { char pad[64]; }; // 自定义缓存行结构- 多个
alignas同时出现时,取最大值(alignas(8) alignas(16) int x;等价于alignas(16)) - 对类/结构体加
alignas,影响其对象的起始地址,也影响其作为成员时的偏移计算 - 栈上变量用
alignas通常没问题;堆上需配合aligned_alloc或operator new重载,否则new T不保证满足自定义对齐
结构体内存布局受 alignas 和成员顺序双重影响
结构体总大小和成员偏移不仅取决于各成员自身对齐,还受 alignas 插入点位置影响。编译器按声明顺序逐个安排成员,并在必要时填充空隙以满足下一个成员(或结构体自身)的对齐要求。
例如:
struct A {
char a;
alignas(16) int b; // 强制 b 地址 % 16 == 0 → 编译器在 a 后插入 11 字节 padding
char c;
}; // sizeof(A) 通常是 32:a(1)+pad(11)+b(4)+c(1)+pad(15)- 把
char c提到alignas(16) int b前面,总大小可能变成 16(紧凑排列) -
alignas作用于成员时,只约束该成员起始地址,不影响前一成员的结束位置 - 使用
#pragma pack会抑制填充,但可能让alignas失效或触发编译错误(取决于实现)
动态分配带 alignas 的对象必须用对齐感知的内存函数
直接 new T 对带有 alignas(N)(N > 默认对齐)的类型,行为未定义——标准只要求 operator new 返回至少 alignof(max_align_t) 对齐的内存(通常是 16)。要安全分配,得显式调用对齐版本:
- C++17 起推荐用
operator new(std::size_t, std::align_val_t):
auto p = ::operator new(1024, std::align_val_t{64}); // 分配 64 字节对齐内存
MyType* obj = new(p) MyType; // placement new- 或用 C 函数
aligned_alloc(64, 1024)(注意:size 必须是 alignment 的整数倍) - 别用
malloc+std::align手动调整——容易越界或未对齐,且不适用于含非平凡构造函数的类型 - 析构后必须用对应方式释放:
operator delete(p, std::align_val_t{64})或free(p)
对齐错误往往不报错,而是导致性能骤降(如跨缓存行加载)或硬件异常(某些 ARM 指令要求严格对齐),这类问题很难复现和调试。


















