2012年3月6日火曜日

複合データ型(構造体など)のアラインメント(alignment)について


C言語で利用するsizeof(x)はxの正味のサイズではなく、
xのアラインメントの倍数に切り上げた値になる。

基本的なデータ型のアラインメントは、下に示すようにその型のサイズ に一致することが多い。
例外もあるのだが(詳しくはこちらを参考)、ここではとにもかくにも一致するとする。

では、複合データ型(構造体など)では具体的にどういったサイズになるのであろうか。
例題を使って考えてみよう。



◆ 基本的なデータ型のアラインメント
構造体のアラインメントを考える前提として、
先にも述べたように、各データ型のサイズとアラインメントは以下とする。

・char
   サイズ          : 1バイト
   アラインメント : 1バイト

・short
   サイズ          : 2バイト
   アラインメント : 2バイト

・int
   サイズ          : 4バイト
   アラインメント : 4バイト

・double
   サイズ          : 8バイト
   アラインメント : 8バイト


◆ 構造体のアラインメント
(例題1)

struct S {
  int a;
  char b;
};

sizeof(struct S)==8 になるのはなぜか


・アラインメント : 4
    最も厳しいメンバであるaサイズ(4バイト)

・要素間パディング : 0
    aは4バイトアラインメントなので、bはaとbの間にパディングを作ることはない

・正味のサイズ : 5
    4+1

・サイズ : 8
    Sの正味のサイズ(5バイト)をSのアラインメント(4バイト)の倍数に切り上げた8バイト



(例題2)

struct S {
  short a;
  char b[3];
};

sizeof(struct S)==6 になるのはなぜか


・アラインメント : 2
    最も厳しいメンバであるaのサイズ(2バイト)

・要素間パディング : 0
    aは2バイトであり、アラインメントも2バイトなので
    bはaとbの間にパディングを作ることはない

   また配列のアラインメントはその要素のアラインメントに等しいので
   b配列の要素はそれぞれの間にパディングを作ることはない

・正味のサイズ : 5
    2+3

・サイズ : 6
    Sの正味のサイズ(5バイト)をSのアラインメント(2バイト)の倍数に切り上げた6バイト



(例題3)

struct S {
  int a[10];
  char b;
};

sizeof(struct S)==44 になるのはなぜか


・アラインメント : 4
    最も厳しいメンバであるa

・要素間パディング : 0
    aは4バイトアラインメントなので、bはaとbの間にパディングを作ることはない

・正味のサイズ : 41
    4*10+1

・サイズ : 44
    Sの正味のサイズ(41バイト)をSのアラインメント(4バイト)の倍数に切り上げた44バイト



(例題4)

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

sizeof(struct S)==24 になるのはなぜか


・アラインメント : 8
    最も厳しいメンバであるa、またはbのサイズ(8バイト)

・要素間パディング : 0
    aは8バイトであり、アラインメントも8バイトなので
    bはaとbの間にパディングを作ることはない

    要素bは8バイトであり、アラインメントも8バイトなので
    cはbとcの間にパディングを作ることはない

・正味のサイズ : 17
    8+8+1

・サイズ : 24
    Sの正味のサイズ(17バイト)をSのアラインメント(8バイト)の倍数に切り上げた24バイト


アラインメントのプログラム操作はビット演算の覚え書きを参照ください。