7

構造体の複数のメンバーがある場合にのみパディングの概念が追加されるのはなぜですか?また、単一の基本データ型メンバーがある場合にパディングの概念が含まれないのはなぜですか?

32ビットマシンを検討する場合

struct 
{
    char a;
} Y;

パディングはなく、Yのsizeofは1バイトになります。

この構造を考えれば

struct 
{
    char a;
    int b;
} X;

XのsizeofXは8バイトになります。

私の質問は、2番目のケースでパディングが追加されたのはなぜですか?通常4バイトの倍数のブロックでデータを読み取るマシンによる効率的なアクセスのためである場合、最初のケースでパディングがなかったのはなぜですか?

4

4 に答える 4

11

2 番目のケースではパディングが追加されます。これは、お使いのマシンで anintが 4 バイトにアラインされているためです。したがって、4 で割り切れるアドレスに常駐する必要があります。

0x04   0x05   0x06   0x07   0x08   0x09   0x0A   0x0B

  a      b      b      b      b     

パディングが追加されていない場合、intメンバーは address から開始されます0x05が、これは誤りです。3 つのパディング バイトが追加された場合:

0x04   0x05   0x06   0x07   0x08   0x09   0x0A   0x0B

  a   |      padding      |   b      b      b      b

これでintは になりました0x08。これで問題ありません。

于 2012-10-12T14:48:51.390 に答える
3

効率だけではありません。

問題は、アクセス自体のサイズではなく、配置です。ほとんどのマシンでは、位置合わせされていないデータにアクセスするとプログラムがクラッシュします。現在の一般的なマシンでは、4バイト境界に位置合わせされたアドレスが必要です。アドレスが4バイト境界に位置合わせされていないアドレスにintアクセスすると、プログラムの速度が低下します。intかなり、またはそれをクラッシュさせます。最初の構造体には配置を考慮したデータが含まれていなかったため、パディングは必要ありませんでした。2番目にはがintあり、コンパイラはそれらの配列が与えられた場合、すべてintが正しく整列されることを確認する必要があります。これは、1)構造体の合計サイズが4の倍数である必要があり、2)int構造体のオフセットが4の倍数である必要があることを意味します。(最初の要件を考慮して:

struct S
{
    char a;
    int b;
    char c;
};

通常、サイズは12で、両方の後にパディングがありますchar。)

他の言語では、コンパイラが構造体を並べ替えて、最も厳密な配置要件を持つ要素が最初に来るようにすることがよくありました。上記の構造体Sの場合、次のようになります。

struct S
{
    int b;
    char a;
    char c;
};

サイズは12ではなく8です。ただし、CとC++の両方でこれは禁止されています。

于 2012-10-12T15:02:00.993 に答える
0

パディングは、特定のデータ型を揃えるために行われます。つまり、特定の型のデータが、指定された数の倍数のアドレスを持つようにするためです。これは CPU のモデルによって異なりますが、多くの場合、2 バイト整数は 2 の倍数であるアドレスに整列され、4 バイト整数は 4 の倍数であるアドレスに整列されます。通常、文字は整列する必要はありません。

したがって、構造体にフィールドが 1 つしかない場合、構造体が適切な境界のあるアドレスに配置されている限り、パディングは必要ありません。システムは常に、これまでに必要とされる最大の境界 (通常は 4 バイトまたは 8 バイト) にブロックを整列させます。構造内の 1 つのものは、適切な境界になります。この問題は、複数のフィールドがある場合にのみ発生します。1 つのフィールドの長さによって、次のフィールドが適切な境界に配置されない場合があるためです。したがって、あなたの例では、もちろん 1 バイトの char と 4 の int があります。構造体がアドレス 0x1000 に配置されているとします。次に、パディングなしで、char は 0x1000 に配置され、int は 0x1001 に配置されます。しかし、4 バイト境界では int の方が効率的です。そのため、コンパイラはいくつかのパッド バイトを追加して、次の境界 0x1004 にプッシュします。これで、char (1 バイト)、padding (3 バイト)、int (4 バイト)、合計 8 バイトになりました。

この場合、状況を改善するためにできることはあまりありません。すべての構造体は 4 バイトまたは 8 バイトの境界に配置されるため、最小値が 5 バイトの場合、実際には常に少なくとも 8 バイトに切り上げられます。( sizeof は構造体間のパディングを表示せず、内部のみを表示しますが、メモリは失われます。)

それ以外の場合は、フィールドの順序を並べ替えることで、余分なパッド バイトの数を最小限に抑えることができます。たとえば、3 つの char と 3 つの int があるとします。構造を次のように宣言すると、

struct {char a; int b; char c; int d; char e; int f;}

次に、コンパイラは最初の char の後に 3 バイトを追加して最初の int を整列させ、次に 2 番目の char の後にさらに 3 バイトを追加して 2 番目の int を整列させます。これにより、char (1) + pad (3) + int (4) + char (1) + pad (3) + int (4) + char (1) + pad (3) + int (4) = 24 が得られます。

しかし、代わりに宣言した場合:

struct {char a; char c; char e; int b; int d; int f;}

次に、char (1) + char (1) + char (1) + pad (1) + int (4) + int (4) + int (4) = 16 を取得します。

何年も前に、パディングを最小限に抑えるために常に最大の要素を最初に配置するようにというアドバイスを読みました。つまり、最初に long、次に int、次に short、そして char を配置します。

数千または数百万のこれらを割り当てる場合、この手法によって多くのメモリを節約できます。1 つまたは 2 つのみを割り当てる場合は、それほど重要ではありません。

于 2012-10-12T15:08:13.153 に答える
0

Paddingの概念ですalignment。アラインされたデータは、整数データ型でissue of computer efficiency and the speed of the access of the data完全にアクセスされます。プロセッサがより効率的にデータにアクセスするために、コンパイラによって 4 バイト アラインメントが行われます。(32 ビット システムの場合)fetching cycle of the processor from the addresses where the data are storedit doesn't mean that with out alignment processor doesn't work it only meant for the speed access of the memory

char の場合、データに必要なバイトは 1 バイトだけなので、各バイト自体が使用可能であるためアライメントは必要ありません( in RAM there are pages and each page size is 1 byte)。そのため、コンパイラは、整数データが​​正しいアドレスにあるアライメント規則を作成します。

これにより、データへのメモリアクセスが高速化されます。

于 2012-10-12T15:27:46.723 に答える