構造体のパディング(詰め物)と配列から構造体へのキャスト

構造体のサイズ (sizeof 演算子が返すバイト数) は、その各メンバ変数のサイズの合計より大きくなることがある。メモリアクセスの関係で、メンバ変数の間に空のバイト列(パディング)が挿入されるためである。一般に、パディングの入り方はアーキテクチャやOSによって異なる。

結論から言うと、構造体が同サイズのメンバ変数のみ持つ場合は、構造体のサイズと各メンバ変数のサイズの合計は等しい、といってよさそう(ただ、構造体の方が常に大きくなったり、構造体の最小サイズが常に1より大きい場合もあるかも)。もう少し詳しく言うと、構造体の先頭アドレスから相対的に見た各メンバ変数のアドレスが、各メンバ変数のサイズの定数倍になっていればパディングは挿入されない、のであろう…。たとえば、8バイトの double 型メンバ変数は 8の定数倍(0, 8, 16…)、4バイトのint 型なら4の定数倍(0,4,8…)の相対的アドレスになっている場合ということ。

このことを踏まえると、ポインタの再解釈を用いて以下のような配列と構造体の相互キャストが可能。

int a[4] = { 1, 2, 3, 4};
struct array {
  int elem[4];
};

assert(reinterpret_cast<array*>(a)->elem[0] == 1);

これでメンバ関数呼び出しとかもできる。

例外として、構造体の先頭アドレスと先頭メンバ変数のアドレスが一致しないような場合には使えない。が、そんな環境あるんだろうか…