c++基本类型的对齐和大小

Alignment and size of C++ primitive types

本文关键字:对齐 类型 c++      更新时间:2023-10-16

在c++中,似乎对于所有整数类型(int, long long int, std::uint16_t,…)和浮点类型,它总是sizeof(T) == alignof(T)

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

对于基本类型,alignof(T) == sizeof(T)对于大多数现代abi都为真,但不能保证它为真。c++标准让对齐主要由实现定义,只受这些约束(参见[basic])。[font =宋体][font =宋体] (c++ 11):

  • 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 charunsigned char都有相同的对齐要求(即1,因为sizeof(char) == 1的定义)。

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

  • wchar_tchar16_tchar32_t具有与其"底层"整数类型相同的对齐要求。

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

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

这些是我个人知道的唯一反例。然而,当我得知用于内存受限的嵌入式环境的ABI指定no对齐任何(即所有T的alignof(T) == 1)时,我并不感到惊讶。对于CPU来说,处理它并不像过去那样困难,特别是如果没有涉及内存虚拟化。


1有趣的事实:c++标准并没有要求实现有一个函数调用堆栈。它需要支持递归,并且在抛出异常时发生所谓的"堆栈展开",但是所有内容都是精心编写的,以便您可以使用我们熟悉的线性堆栈以外的东西来实现它。