c++基本类型的对齐和大小
Alignment and size of C++ primitive types
在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 char
和unsigned char
都有相同的对齐要求(即1,因为sizeof(char) == 1
的定义)。 -
所有无符号整数类型与相应的有符号类型具有相同的对齐要求。
-
wchar_t
、char16_t
和char32_t
具有与其"底层"整数类型相同的对齐要求。
有的历史abi,其中基本类型没有与其大小对齐。一个著名的例子是80386的原始System V ABI中的double
和long double
,尽管它们的宽度分别为8和12字节,但它们只对齐到4字节粒度。这是因为堆栈指针只能保证以4字节的粒度对齐,并且将激活记录中的内容对齐到比堆栈指针更大的粒度是一件痛苦的事情。
现在,同样的堆栈对齐问题可能会出现在向量类型中;例如,在x86-64上,堆栈指针保证对齐到16字节边界,但硬件现在最多支持512位(64字节)向量。
这些是我个人知道的唯一反例。然而,当我得知用于内存受限的嵌入式环境的ABI指定no对齐任何(即所有T的alignof(T) == 1
)时,我并不感到惊讶。对于CPU来说,处理它并不像过去那样困难,特别是如果没有涉及内存虚拟化。
1有趣的事实:c++标准并没有要求实现有一个函数调用堆栈。它需要支持递归,并且在抛出异常时发生所谓的"堆栈展开",但是所有内容都是精心编写的,以便您可以使用我们熟悉的线性堆栈以外的东西来实现它。
- 运行时错误:引用绑定到类型"int"的未对齐地址0xbebebebebebebec6,这需要 4 个字节对齐 (stl_vector.h)
- 具有调整对齐方式的类型定义
- 外部基础类型未按请求对齐时的atomic_ref
- 如何分配适合容纳 T 类型对象的缓冲区(可能过度对齐、可能有运算符 new 等)
- 对象地址是否保证是其类型对齐的倍数
- 对齐C++字符串类型问题 std::字符串到 TStr
- 数据对齐:限制内存地址为数据类型大小倍数的原因
- 与 std::aligned_storage 过度对齐的类型
- 在英特尔上自然对齐的POD类型的保证原子操作
- 更改派生类型的对齐
- 幻影类型是否与原始类型具有相同的对齐方式
- 对齐说明符:在类型 / 上 成员数据
- 如何检查该类型的类型指针是正确对齐的
- 类型是否可以具有除'n-byte alignment'以外的对齐要求
- 与包含的类型相比,数组在C++中的对齐方式如何?2.
- 新字符是否实际上保证类类型的对齐内存
- 我不明白在下面的代码中将 char buffer[] 与 X 类型的对象对齐的原因
- 标准是否要求自动存储中的对象对任何类型都具有正确的对齐方式(例如malloc)
- 基本类型和结构的对齐,内部只有这个基本类型
- 抛出对齐类型时出现 Clang 运行时错误.编译器错误