假设我有某种类型T
必须是N
字节对齐的。现在我声明一个类型数组T
:
T array[size];
数组是否具有与类型相同的对齐要求T
或是否有任何其他对齐要求?
是的,对齐要求必须相同。显然,一个数组T
必须至少与单个数组一样严格对齐,T
否则它的第一个成员将无法正确对齐。一个数组不能比它的元素类型更严格地对齐的事实来自标准的第 8.3.4 节,它说数组是连续分配的元素子对象。考虑这个数组数组:
T a[2][size];
无论 的值是size
多少,两个数组之间都不能有“额外的”填充a[0]
,a[1]
否则这违反了连续分配的要求。
等效地,我们知道(char*)&a[1] == (char*)&a[0] + sizeof(a[0])
和sizeof(a[0]) == sizeof(T[size]) == size * sizeof(T)
。由于这适用于任何size
情况,因此必须可以T
在任何地址放置一个数组,该地址为单个T
对象适当对齐(给定足够的地址空间)。
我相信,数组的对齐要求将与数组元素的对齐要求相同。
显然,数组的开头必须至少与其第一个元素要求的一样严格对齐,因此它的对齐要求不能不那么严格。
数组的起始地址加上每个元素的大小必须使第二个元素充分对齐。这限制了元素类型的大小,我相信这意味着可以在结构的末尾引入填充以保持数组对齐,即使您从未在数组中使用该结构。但这并不意味着需要更严格的对齐。
通过归纳,如果前两个元素都可以,则后续元素也可以,因此为数组提供与其元素相同的对齐要求应该没问题。
不过,从规范中引用会很好。
我相信规则是相同的,但解释可能会令人困惑。
我相信由于数组的每个元素都将具有相同的大小,因此只有对齐第一个元素会自动对齐其余元素,因此元素之间永远不会有任何填充。
这在简单数组的情况下可能是正确的,但对于复杂的场景则不然。
数组的步幅可以大于元素大小,即每个单独的元素之间可能存在焊盘。
下面是一个很好的例子
struct ThreeBytesWide {
char a[3];
};
struct ThreeBytesWide myArray[100];
ThreeBytesWide 数组的每个元素都可以对齐到四字节边界
编辑:正如评论中所阐述的,提到在单个元素之间有填充是当元素本身是 3 个字节并与 4 个字节边界对齐时。
对象数组必须是连续的,因此对象之间永远不会有填充,尽管可以将填充添加到对象的末尾(产生几乎相同的效果)。 C++ 数据成员对齐和数组打包
#include <iostream>
__declspec(align(32))
struct Str1
{
int a;
char c;
};
template<typename T>
struct size
{
T arr[10];
};
int main()
{
size<Str1> b1;
std::cout << sizeof(Str1) << std::endl; // prints 32
std::cout << sizeof(b1) << std::endl; // prints 320
std::cin.ignore();
return 0;
}
参考: