バイト単位で整列T
する必要がある型があるとします。N
次に、 type の配列を宣言しますT
。
T array[size];
配列には型と同じアラインメント要件がT
ありますか、それとも他のアラインメント要件がありますか?
はい、アライメント要件は同じでなければなりません。明らかに、の配列はT
、少なくとも単一の配列と同じくらい厳密に位置合わせする必要がありますT
。そうしないと、その最初のメンバーが適切に位置合わせされません。配列がその要素の型よりも厳密に位置合わせできないという事実は、配列が連続して割り当てられた要素のサブオブジェクトであると述べている標準セクション 8.3.4 から導かれます。次の配列の配列を考えてみましょう。
T a[2][size];
の値がどうであれ、size
2 つの配列間に「余分な」パディングがあってはなり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
配列の配置要件は、配列要素の配置要件と同じになると思います。
明らかに、配列の先頭は、少なくともその最初の要素が要求するのと同じくらい厳密に位置合わせする必要があるため、その位置合わせ要件はそれほど厳密ではありません。
配列の開始アドレスに各要素のサイズを加えた値は、2 番目の要素を十分に配置したままにしておく必要があります。これは、要素型のサイズに制約を課します。これは、配列内でその構造体を使用しない場合でも、配列を整列させるためだけに、構造体の最後にパディングを導入できることを意味すると私は信じています。しかし、厳密な調整が必要だという意味ではありません。
誘導により、最初の 2 つが OK であれば後続の要素も OK であるため、配列にその要素と同じアライメント要件を与えることは問題ありません。
ただし、仕様からの引用はいいでしょう。
ルールは同じだと思いますが、解釈が混乱する可能性があります。
配列の各要素は同じサイズになるため、最初の要素を整列させるだけで残りの要素が自動的に整列されるため、要素間にパディングが発生することはないと私は信じていました。
これは、単純な配列の場合には当てはまりますが、複雑なシナリオでは当てはまりません。
配列のストライドは、要素のサイズよりも大きくすることができます。つまり、個々の要素の間にパッドが存在する可能性があります。
以下は良い例です
struct ThreeBytesWide {
char a[3];
};
struct ThreeBytesWide myArray[100];
ThreeBytesWide 配列の各要素は、4 バイト境界に揃えることができます
編集:コメントで詳しく説明されているように、個々の要素間にパッドがあるという言及は、要素自体が 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;
}
参考文献: