2010-12-30 2 views
4
class CHaraICICCC 
{ 
int i; 
char c1; 
int j; 
char c2; 
char c3; 
char c4; 
}; 

class CHaraIICCCC 
{ 
int i; 
int j; 
char c1; 
char c2; 
char c3; 
char c4; 
}; 

void fun() 
{ 
    CHaraICICCC eici; 
    CHaraIICCCC eiicc; 

    int icic = sizeof(eici); // -> output of icic is 16. 
    int iicc = sizeof(eiicc); // -> output of icic is 12. 
} 

誰かが知っている場合は、私にこのような理由を教えてください。 ありがとう 原メンバーの順序に基づいてクラスオブジェクトのサイズが異なるのはなぜですか?

答えて

8

アライメントのためです。 15バイトの合計

byte 0: \ 
byte 1: | <--- int i 
byte 2: | 
byte 3:/ 
byte 4: <----- char c1 
byte 5: \ 
byte 6: | <--- Padding (wasted bytes) 
byte 7:/
byte 8: \ 
byte 9: | <--- int j 
byte 10: | 
byte 11:/
byte 12: <----- char c2 
byte 13: <----- char c3 
byte 14: <----- char c4 

CHaraIICCCCは次のようになりながら、:のx86コンパイラはCHaraICICCCは、おそらくこのようにレイアウトされるように(高速メモリアクセスのための)4バイト境界にINT型を整列させる傾向がある

byte 0: \ 
byte 1: | <--- int i 
byte 2: | 
byte 3:/ 
byte 4: \ 
byte 5: | <--- int j 
byte 6: | 
byte 7:/
byte 8: <----- char c1 
byte 9: <----- char c2 
byte 10: <----- char c3 
byte 11: <----- char c4 

の合計12バイト(パディングに無駄なバイトがない)。もちろん、これはコンパイラに関係しており、コンパイルオプションに依存しています。

+0

こんにちは、Simone、あなたの迅速な返答のおかげで。バイト4とバイト8の間のバイトは、私たちのために損失ですか? (ビジュアルスタジオの一般的な設定で)、最初のメンバはintなので、これらの3バイトは追加されていますか?その損失を避けることはできませんか? – Haranadh

+0

最初のレイアウトを使用し、3バイトの損失を避けるには、コンパイラに1バイトのパディングを使用するように指示する必要があります。私は[これ](http://msdn.microsoft.com/en-us/library/83ythb65.aspx)があなたに当てはまると思います(あなたは 'align(8)'を宣言しなければなりません)。 – Simone

+2

@ Haranadh Gupta:アーキテクチャによっては、ワード整列を使用してパフォーマンスを向上させます。データ構造をパックすることを選択した場合、バイトを「保存」すると、結果のコードが大きくなり、遅くなることがあります。パッキングとアライメントを調整する必要がある理由はありますが、スペースを節約することはめったにありません。 – Clifford

0

デフォルトのパックモードでは、ほとんどのアーキテクチャでメンバはサイズの倍数であるオフセット(構造体の先頭から)に揃えられます。

必要に応じて、パディングバイトが構造体に追加され、その配置が取得されます。

ので、デフォルトの梱包、4バイトの整数と仮定すると、あなたの最初の構造は次のように本当にです:の質問を伸ばす

class CHaraICICCC 
{ 
    int i; 
    char c1; 
    char padding[3]; 
    int j; 
    char c2; 
    char c3; 
    char c4; 
}; 
+0

訂正:*プリミティブ*メンバーは、そのサイズの倍数のオフセットで整列されます。ユーザー定義の構造体はありません! – Mehrdad

1

「なぜ」少しは、私はは、私は理由があることどこかで読んだと思うCPUがデータのビットを無視できるようにすることです。例えば、データが8バイト整列であるとわかっている場合、CPUはアドレスの下位3ビットを無視するだけで効率を向上させることができます。私は間違っているかもしれませんが、正しく覚えていれば、そういうわけでCPUがアライメントを必要としているのです。

+0

この回答は現実とは完全には関係ありませんが、CPU内部の状況は本当に非常に複雑です。機能的には、一部のCPUはアライメントされていないメモリにアクセスすることができず、内部でアライメントされていないメモリにアクセスするためにマイクロコード命令のシーケンスにフォールバックする必要があります。アライメントされていないアクセスが必要だがCPUでサポートされていない場合、コンパイラはエミュレートするために余分なコードを生成する必要があります(要求されたアドレスの「両側」のメモリにアクセスし、 –

関連する問題