24

假设我有某种类型T必须是N字节对齐的。现在我声明一个类型数组T

T array[size];

数组是否具有与类型相同的对齐要求T或是否有任何其他对齐要求?

4

4 回答 4

19

是的,对齐要求必须相同。显然,一个数组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对象适当对齐(给定足够的地址空间)。

于 2012-11-08T07:45:04.357 回答
4

我相信,数组的对齐要求将与数组元素的对齐要求相同。

显然,数组的开头必须至少与其第一个元素要求的一样严格对齐,因此它的对齐要求不能不那么严格。

数组的起始地址加上每个元素的大小必须使第二个元素充分对齐。这限制了元素类型的大小,我相信这意味着可以在结构的末尾引入填充以保持数组对齐,即使您从未在数组中使用该结构。但这并不意味着需要更严格的对齐。

通过归纳,如果前两个元素都可以,则后续元素也可以,因此为数组提供与其元素相同的对齐要求应该没问题。

不过,从规范中引用会很好。

于 2012-11-08T07:17:43.620 回答
1

我相信规则是相同的,但解释可能会令人困惑。

我相信由于数组的每个元素都将具有相同的大小,因此只有对齐第一个元素会自动对齐其余元素,因此元素之间永远不会有任何填充。

这在简单数组的情况下可能是正确的,但对于复杂的场景则不然。

数组的步幅可以大于元素大小,即每个单独的元素之间可能存在焊盘。

下面是一个很好的例子

struct ThreeBytesWide {
    char a[3];
};

struct ThreeBytesWide myArray[100];

来源 - 跨步维基百科

ThreeBytesWide 数组的每个元素都可以对齐到四字节边界

编辑:正如评论中所阐述的,提到在单个元素之间有填充是当元素本身是 3 个字节并与 4 个字节边界对齐时。

于 2012-11-08T07:25:37.547 回答
0

对象数组必须是连续的,因此对象之间永远不会有填充,尽管可以将填充添加到对象的末尾(产生几乎相同的效果)。 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;
}

参考:

  1. C++ 中的数据对齐、标准和可移植性
  2. http://msdn.microsoft.com/en-us/library/83ythb65.aspx
于 2012-11-08T07:34:04.597 回答