パディングは、特定のデータ型を揃えるために行われます。つまり、特定の型のデータが、指定された数の倍数のアドレスを持つようにするためです。これは 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 つのみを割り当てる場合は、それほど重要ではありません。