ビット・フィールドの位置合わせ

ビット・フィールドは、C_BoolCC++boolcharsigned charunsigned charshortunsigned shortC++intunsigned intlongunsigned longC++long long、または unsigned long longC++ のいずれかのデータ型として宣言できます。 ビット・フィールドの位置合わせは、その基本タイプおよびコンパイル・モード (32 ビットまたは 64 ビット) によって異なります。

C C 言語では、ビット・フィールドを、 int でなく char または short として指定することができますが、 XL C/C++ はそれらを unsigned int としてマップします。ビット・フィールドの長さは、その基本タイプの長さを超えることはできません。 拡張モードでは、ビット・フィールドに対して sizeof 演算子を使用することができます。 ビット・フィールド上の sizeof 演算子は基本タイプのサイズを戻します。C

C++ ビット・フィールドの長さは、その基本タイプの長さを超えてもかまいませんが、残りのビットはフィールドの埋め込みに使用され、値は実際には保管されません。C++

ただし、ビット・フィールドを含む集合体の位置合わせ規則は、有効な位置合わせモードによって異なります。 この規則については、以下で説明します。

natural 位置合わせの規則

  • 長さ 0 のビット・フィールドがあると、そのビット・フィールドの基底宣言型の次の位置合わせ境界まで埋め込まれます。 これにより、64 ビット・モードの long を除くすべての型について、次のメンバーが 4 バイトの境界で開始されるようになります (64 ビット・モードの long の場合、次のメンバーが次の 8 バイト境界に移動されます)。 直前のメンバーの記憶域レイアウトが適切な境界上で終了した場合は、埋め込みはされません。
  • C 長さ 0 のビット・フィールドのみを含む集合体は、 長さは 0 バイトであり、4 バイトで位置合わせされます。C
  • C++ 長さ 0 の ビット・フィールドのみを含む集合体では、宣言されたビット・フィールドの型とコンパイル・モード (32 ビットまたは 64 ビット) に応じて、長さが 4 バイトまたは 8 バイトになります。C++

power 位置合わせの規則

  • ビット・フィールドを含む集合体は 4 バイト (ワード) 位置合わせをする。
  • ビット・フィールドは、現在のワードにパックされる。ビット・フィールドがワード境界に交差する場合は、そのビット・フィールドは次のワード境界から開始する。
  • 長さが 0 のビット・フィールドがあると、 その直後のビット・フィールドは、宣言型とコンパイル・モードに応じて、 次のワード境界または 8 バイトに位置合わせされる。 長さが 0 のビット・フィールドがワード境界にある場合は、その次のビット・フィールドはこの境界から開始される。
  • C 長さ 0 のビット・フィールドのみを含む集合体は、 長さは 0 バイトです。C
  • C++ 長さ 0 のビット・フィールドのみを含む集合体は、長さは 1 バイトです。C++

Mac68K 位置合わせの規則

  • ビット・フィールドは、1 ワードにパックされ、2 バイト境界で位置合わせされる。
  • ワード境界を交差するビット・フィールドは、ビット・フィールドがすでにハーフワード境界で開始していても、 次のハーフワードに移動させられる。 (ビット・フィールドは、ワード境界を交差して終了することもある。)
  • 長さが 0 のビット・フィールドは、現在このビット・フィールドがハーフワード境界にあったとしても、 次のメンバーを、たとえそれがビット・フィールドでなくても、 強制的に次のハーフワード境界から開始させる。
  • 長さが 0 のビット・フィールドしか含んでいない集合体の長さは、 長さ 0 のビット・フィールドの数の 2 倍 (バイト換算) である。
  • 特殊な例として、最大のエレメントが長さ 16 以下のビット・フィールドを持つ共用体のサイズは、 2 バイトである。 ビット・フィールドの長さが 16 よりも大きい場合は、共用体のサイズは 4 バイトになります。

ビット・パック位置合わせの規則

  • ビット・フィールドは 1 バイトで位置合わせされ、 デフォルトではビット・フィールド間の埋め込みなしでパックされます。
  • 長さ 0 のビット・フィールドがあると、次のメンバーは、次のバイト境界から開始します。 長さ 0 のビット・フィールドがすでにバイト境界にある場合は、次のメンバーはこの境界から開始します。 ビット・フィールドに続く非ビット・フィールド・メンバーは、次のバイト境界に位置合わせします。

ビット・パック位置合わせの例

#pragma options align=bit_packed
struct {
   int a : 8;
   int b : 10;
   int c : 12;
   int d : 4;
   int e : 3;
   int : 0;
   int f : 1;
   char g;
   } A;

pragma options align=reset     

A のサイズは 7 バイトです。A の位置合わせは 1 バイトです。 A のレイアウトは次のようになります。

メンバー名 バイト・オフセット ビット・オフセット
a 0 0
b 1 0
c 2 2
d 3 6
e 4 2
f 5 0
g 6 0