7

在 C++ 中,似乎对于所有整数类型(intlong long intstd::uint16_t、 ...)和浮点类型,它总是sizeof(T) == alignof(T).

这个编译器/平台是特定的,还是保证是真的?是否存在一个平台,其中int32_ts 不需要在 32 位边界上对齐(只要它们不重叠)?

4

1 回答 1

13

对于基本类型,alignof(T) == sizeof(T)对于大多数现代 ABI 来说都是正确的,但不能保证它是正确的。C++ 标准主要是实现定义的对齐方式,仅受这些约束(参见C++11 中的[basic.align][basic.fundamental] ):

  • alignof(T) <= sizeof(T). 这在标准中没有明确说明,但数组元素之间永远不会有任何填充,因此无论 的第一个元素的对齐方式如何T t[2]第二个元素的对齐方式都不能大于sizeof(T),因此这是类型的最大对齐方式T. 请注意,变量的对齐方式可以更大,例如如果alignas在其上使用。

  • alignof(T) <= alignof(std::max_align_t), 除非可能存在alignas. 是否alignas会导致“过度对齐”(比 更大的粒度max_align_t)是实现定义的。

  • char, signed char, 并且unsigned char都具有相同的对齐要求(即 1,因为sizeof(char) == 1根据定义)。

  • 所有无符号整数类型与相应的有符号类型具有相同的对齐要求。

  • wchar_t, char16_t, 并且char32_t具有与其“基础”整数类型相同的对齐要求。

历史上存在基本类型与其大小不一致的 ABI。一个著名的例子是80386doublelong double原始 System V ABI,尽管分别为 8 和 12 字节宽,但它仅与 4 字节粒度对齐。这是因为堆栈指针只能保证对齐到 4 字节的粒度,并且将激活记录中的内容对齐到比堆栈指针更大的粒度是很痛苦的。1

如今,同样的堆栈对齐问题可能会出现向量类型;例如,在 x86-64 上,堆栈指针保证与 16 字节边界对齐,但硬件现在最多支持512 位(64 字节)向量

这些是我个人知道的唯一反例。但是,如果得知内存受限的嵌入式环境的 ABI 没有指定任何对齐(即所有 T),我不会感到惊讶。CPU 不再像过去那样难以处理,尤其是在不涉及内存虚拟化的情况下。alignof(T) == 1


1有趣的事实:C++ 标准要求实现具有函数调用堆栈。它需要对递归的支持,并且在抛出异常时会发生称为“堆栈展开”的事情,但是所有内容都经过精心编写,以便您可以使用我们都熟悉的线性堆栈以外的东西来实现它。

于 2016-08-12T11:23:32.500 回答