假设我有一个类型为
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
类型的数组(假设有足够的地址空间)。T[2]
可以对齐到 alignof(T) * 2
,这将允许 T[2][size]
不需要任何填充。 - Pubbyalignof
表达式产生其操作数类型的对齐要求。操作数应为表示完整对象类型或其数组的type-id [...] 3/ [...] 当将alignof
应用于数组类型时,结果应为元素类型的对齐方式。 - Matthieu M.sizeof
中;不在数组中的元素必须与不在数组中的元素大小相同。至于第二点,我认为标准并不否认数组具有比非数组类型更严格的对齐要求的权利(我相当确定关于 C++03,它本身并没有太多关于对齐的规定),但实际上,对齐要求将是相同的。 - James Kanzenew char[n]
(其中char
实际上可以是任何字符类型)的返回值必须足够对齐于任何可以适配于n
的类型。请注意,这个保证仅适用于new
表达式;它不适用于类型为char[]
的变量。 - James Kanze我相信规则是一样的,但解释可能会令人困惑。
我认为由于数组的每个元素大小相同,因此仅对齐第一个元素就会自动对齐其余元素,因此元素之间永远不会有任何填充。
这在简单数组的情况下可能是正确的,但对于复杂情况则不然。
数组的步幅可以大于元素大小,即每个单独元素之间可能存在填充。
以下是一个很好的例子。
struct ThreeBytesWide {
char a[3];
};
struct ThreeBytesWide myArray[100];
ThreeBytesWide 数组的每个元素都可以对齐到四字节边界。
编辑:正如评论中所阐述的那样,提到在单个元素之间有填充时,是指元素本身为3字节且对齐到四字节边界。
sizeof(ThreeBytesWide)== 4
。 - Bo Perssonsizeof(element)
。如果有任何填充,它必须在每个数组元素内部而不是它们之间。 - Bo Persson需要一个对象数组是连续的,因此对象之间永远没有填充,尽管可以在对象的末尾添加填充(产生几乎相同的效果)。 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;
}
参考资料: