2012-11-08 1 views
18

TのタイプがNバイトである必要があるとします。今、私はタイプTの配列を宣言:配列は、含まれている型と比較してC++でどのように整列されていますか?

T array[size]; 

配列はタイプTと同じアライメント要件を持っているのでしょうか、それは他の配置要件を持っているのだろうか?

+2

私は不思議ですが、なぜそれは重要ですか? – Pubby

+2

@Pubby:私はコードをレビューしていますが、配列や配列の要件については興味深いコメントがいくつか見つかりました。コメントはblshtですが、確認したいと思っています。 – sharptooth

答えて

15

はい、位置合わせ要件が同じでなければなりません。明らかに、Tの配列は少なくとも少なくとも1つの同じくらい厳密に整列されていなければならず、さもなければ最初のメンバーが正しく整列されないでしょう。配列が要素型よりも厳密に揃えられないという事実は、配列がと連続していることを示す標準セクション8.3.4に従います。要素サブオブジェクトが割り当てられています。配列のこの配列を考える:

sizeの値は、二つの配列 a[0]a[1]間に「余分な」パディングが存在しないことができるものは何でも
T a[2][size]; 

そうでなければ、これはcontiguosly割り当て要件に違反します。

同等に、私たちは、(char*)&a[1] == (char*)&a[0] + sizeof(a[0])sizeof(a[0]) == sizeof(T[size]) == size * sizeof(T)を知っています。これがどんなsizeにも当てはまるので、Tオブジェクト(適切なアドレス空間が与えられている)に対して適切に整列されている任意のアドレスにTの配列を配置することが可能でなければならない。

+0

私が理解するところでは、サブアレイのサイズがアラインメントの倍数である場合、アラインメントはエレメントと異なる場合があります。パディングが必要ないからです。 [このコメント](http://stackoverflow.com/users/147192/matthieu-m)は正解と思われる。 – Pubby

+0

[おっと、このリンク](http://stackoverflow.com/questions/13284208/how-is-an-array-aligned-in-c-compared-to-type-contained/13284631#comment18111863_13284297) – Pubby

+0

' T [2] 'は' T [2] [size] 'がパディングを持たないように' alignof(T)* 2'に整列させることができます。 – Pubby

4

配列の配置要件は配列要素の配列要件と同じであると私は考えている。

明らかに、配列の開始は、少なくとも最初の要素が必要とする厳密に揃えられていなければなりません。そのため、配列の必要条件はそれほど厳しくできません。

配列の先頭アドレスと各要素のサイズには、2番目の要素が十分に整列していなければなりません。これは要素型のサイズに制約を課します。これは、たとえ配列内でその構造体を使用していないとしても、配列を整列させるために構造体の最後にパディングを導入できることを意味します。しかし、より厳密なアライメントを行う必要はありません。

誘導によって、最初の2つがOKであれば、それ以降の要素はOKなので、配列にはその要素と同じ位置合わせ要件が必要です。

スペックの引用はうまくいくはずです。

+6

ここで(アライメント用に)**§5.3.6[expr.alignof] ** 1/'alignof'式は、そのオペランドタイプのアライメント要件を生成します。オペランドは、完全なオブジェクト型またはその配列を表す* type-id *でなければならない[...] 3/[...]配列型に 'alignof'が適用されるとき、結果は要素タイプ。 –

+0

「パディング」はすべて「sizeof」に反映されなければなりません。配列にない要素は配列にない要素と同じサイズでなければなりません。 2番目の点については、配列が非配列型よりも厳密な配列の必要条件を持つ配列を拒否しているとは私は考えていません(C++ 03に関してはかなり整理されていません実際には、位置合わせの要件は同じになります。 –

+0

アライメントの要件は同じで、顕著な例外が1つあります。 'new char [n]'( 'char'は実際どんな文字型でもかまいません)の戻り値は、' n'に収まるすべての型に対して十分に整列されていなければなりません。ただし、この保証はnew式に適用されることに注意してください。 'char []'型の変数には適用されません。 –

1

ルールは同じですが、解釈が混乱する可能性があります。

私は、配列の各要素が同じサイズであるため、最初の要素を整列するだけで自動的に残りの部分が整列するため、要素間にパディングはありません。

これは、単純な配列の場合には当てはまりますが、複雑なシナリオでは当てはまりません。

アレイのストライドは、要素サイズより大きくてもよい。すなわち、個々の要素間にパッドが存在する可能性がある。

以下はその良い例ThreeBytesWide配列の各要素は、4バイト境界に整列することができ

struct ThreeBytesWide { 
    char a[3]; 
}; 

struct ThreeBytesWide myArray[100]; 

source - stride wikipedia

ある

編集:、コメントで言及のを詳述したよう個々の要素間にパッドを有するのは、要素自体が3バイトと言い、4バイト境界に位置合わせされている場合である。

+0

この記事は、C/C++の動作に関するソースが誤解を招くようになっています。 Talkページから:CとC++の "stride"とsizeof()は常に同じです、つまりsizeof(T [N])== sizeof(T)* Nです。ISO14882の例8.3.4を参照してください: ISO9899:1999(e)の6.5.2.1およびISO9899:1999(e)の6.5.6ならびにISO9899:1999(e)の6.2.5-20ならびにISO9899の6.5.3.4-6 :1999(e)がここで取り組んでいる。 –

+0

アレイにパディングはありません。構造体が4バイトの境界に位置合わせされている場合は、各構造体の最後に未使用のバイトを持つ 'sizeof(ThreeBytesWide)== 4 'も持ちます。 –

+0

私は両方のコメントを完全に理解しているかわかりません。 @BoPersson私はsizeof(ThreeBytesWide)が4であるとも言っていました。したがって、個々の配列の場合、上記のような構造体にパックされていない限り、最初のバイト以外はパディングされません。 – fayyazkl

-1

オブジェクトの配列は連続している必要があるため、オブジェクトの間にはパディングはありませんが、オブジェクトの末尾にパディングを追加できます(ほとんど同じ効果が得られます)。 C++ Data Member Alignment and Array Packing

#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. Data alignment in C++, standard and portability
  2. http://msdn.microsoft.com/en-us/library/83ythb65.aspx
+0

これは配列自体のアラインメントについては何も言いませんサイズ。 – sharptooth

関連する問題