56

私は 32 ビット マシンで作業しているので、メモリ アラインメントは 4 バイトである必要があると思います。私はこの構造体を持っているとしましょう:

typedef struct {
    unsigned short v1;
    unsigned short v2;
    unsigned short v3;
} myStruct;

単純な追加サイズは 6 バイトで、アラインされたサイズは 8 である必要があると思いますが、sizeof(myStruct)6 が返されます。

ただし、次のように書くと:

typedef struct {
    unsigned short v1;
    unsigned short v2;
    unsigned short v3;
    int i;
} myStruct;

単純な追加サイズは 10 バイト、整列サイズは 12 で、今回はsizeof(myStruct) == 12.

誰かが違いを説明できますか?

4

10 に答える 10

23

メンバーがまったく同じ2 つの構造体を記述したとしても、異なるメンバーを持つことは忘れてください。違いは、それらが宣言されている順序が異なることです。各構造体のサイズは異なる場合があります (多くの場合異なります)。

たとえば、これを参照してください。

#include <iostream>
using namespace std;
struct A
{
   char c;
   char d;
   int i; 
};
struct B
{
   char c;
   int i;   //note the order is different!
   char d;
};
int main() {
        cout << sizeof(A) << endl;
        cout << sizeof(B) << endl;
}

でコンパイルするとgcc-4.3.4、次の出力が得られます。

8
12

つまり、両方の構造体が同じメンバーを持っていても、サイズが異なります!

Ideone のコード: http://ideone.com/HGGVl

肝心なのは、標準ではパディングの方法について言及していないため、コンパイラは自由に決定を下すことができ、すべてのコンパイラが同じ決定を下すとは想定できないということです。

于 2011-03-25T17:23:42.237 に答える
8

仮定:

sizeof(unsigned short) == 2
sizeof(int)            == 4

次に、私は個人的に次を使用します(コンパイラは異なる場合があります):

unsigned shorts are aligned to 2 byte boundaries
int will be aligned to 4 byte boundaries.


typedef struct
{
   unsigned short v1;    // 0 bytes offset
   unsigned short v2;    // 2 bytes offset
   unsigned short v3;    // 4 bytes offset
} myStruct;              // End 6 bytes.


// No part is required to align tighter than 2 bytes. 
// So whole structure can be 2 byte aligned.

typedef struct
{
    unsigned short v1;      // 0 bytes offset
    unsigned short v2;      // 2 bytes offset
    unsigned short v3;      // 4 bytes offset
    /// Padding             // 6-7 padding (so i is 4 byte aligned)
    int i;                  // 8 bytes offset
} myStruct;                 // End 12 bytes

// Whole structure needs to be 4 byte aligned.
// So that i is correctly aligned.
于 2011-03-25T18:41:38.990 に答える
5

まず、パディングの詳細はコンパイラに任されていますが、OS はアラインメント要件に関していくつかの規則も課しています。OSは異なる場合がありますが、この回答はgccを使用していることを前提としています

特定の構造体とその要素が占めるスペースを決定するには、次の規則に従うことができます。

まず、構造体は常に、すべてのデータ型に対して適切に配置されたアドレスから始まると仮定します。

次に、構造体のすべてのエントリに対して:

  • 必要な最小スペースは、 で指定される要素の生のサイズですsizeof(element)
  • 要素の配置要件は、要素の基本型の配置要件です。特に、これは、char[20]配列のアライメント要件がプレーンの要件と同じであることを意味しますchar

最後に、構造体全体のアラインメント要件は、各要素のアラインメント要件の最大値です。

gcc は、特定の要素の後にパディングを挿入して、次の要素 (最後の要素について話している場合は構造体) が正しく配置されるようにします。メモリを節約する場合でも、構造体内の要素の順序を再配置することはありません。

現在、アライメント要件自体も少し奇妙です。

  • 32 ビット Linux では、2 バイトのデータ型が 2 バイトのアラインメントを持つ必要があります (それらのアドレスは偶数でなければなりません)。より大きなデータ型はすべて、4 バイトの位置合わせが必要です (アドレスは0x00x40x8またはで終わります0xC)。これは、4 バイトを超える型 ( や など) にも適用されることに注意してdoubleくださいlong double
  • 32 ビット Windows は、型のサイズが K バイトの場合、K バイトにアラインする必要があるという点でより厳密です。これは、はまたはdoubleで終わるアドレスにのみ配置できることを意味します。これに対する唯一の例外は、実際には 12 バイト長であるにもかかわらず、依然として 4 バイトにアラインされている です。0x00x8long double
  • Linux と Windows の両方で、64 ビット マシンでは、K バイト タイプは K バイト アラインされている必要があります。繰り返しますが、これlong doubleは例外であり、16 バイトでアラインされている必要があります。
于 2011-03-25T18:41:05.293 に答える
2

2 番目の理由は、32 ビット境界でとの間に挿入さsizeof(myStruct)れる12パディングです。2 バイトあります。v3ii

ウィキペディアでは、パディングと配置について合理的に明確に説明しています。

于 2011-03-25T17:17:33.427 に答える