C および C++ では、整数メンバーを、コンパイラーが普通許可する サイズより小さなメモリー・スペースへ保管することができます。スペースを節約するこれらの構造体メンバーは、ビット・フィールド と呼ばれ、それらのビット単位の幅を明示的に宣言することができます。 ビット・フィールドは、データ構造体を固定ハードウェア表記に強制的に調和させる必要がある移植不能なプログラムで使用されます。
ビット・フィールドを宣言する構文は、以下のとおりです。
>>-type_specifier--+------------+--:--constant_expression--;--->< '-declarator-'
ビット・フィールド宣言には、型指定子と、その後に続く、 オプションの宣言子、コロン、フィールド幅をビット単位で示す定数整数式、およびセミコロンが含まれます。 ビット・フィールド宣言では、型修飾子 const または volatile のいずれかを使用することができません。
C99 規格では、修飾および非修飾の _Bool、signed int、および unsigned int を組み込むために、ビット・フィールド用に許可されるデータ型を必要とします。さらに、
このインプリメンテーションは次の型をサポートします。
すべてのインプリメンテーションにおいて、 ビット・フィールドのデフォルトの整数型は、unsigned です。
C++ では、ビット・フィールドの許容型リストが拡張され、任意の整数型または列挙型が含まれます。
どちらの言語でも、ビット・フィールドに範囲外の値を割り当てると、 下位のビット・パターンは保存され、適切なビットが割り当てられます。
長さ 0 のビット・フィールドは、名前なしのビット・フィールドにする必要があります。 名前なしのビット・フィールドは、参照または初期化することはできません。 幅がゼロのビット・フィールドの場合は、次のフィールドが次のコンテナー境界に位置合わせされることになり、 そこでは、コンテナーは、ビット・フィールドの基礎となる型と同じサイズになります。
ビット・フィールドは、align コンパイラー・オプションにも従います。
align サブオプションごとに、異なるセットの位置合わせ
プロパティーをビット・フィールドに与えます。位置合わせに影響する align コンパイラー・オプション
および #pragma の詳しい説明については、「XL C/C++ コンパイラー・リファレンス」を参照してください。
最大のビット・フィールド長は、64 ビットです。
移植性を持たせるために
、32 ビットを超える
サイズのビット・フィールドを使用しないでください。
次の制約事項は、ビット・フィールドに適用されます。次のことはできません。
次の構造体には、3 つのビット・フィールド・メンバー kingdom、phylum、および genus が あり、それぞれ 12、6、2 ビットを占有します。
struct taxonomy { int kingdom : 12; int phylum : 6; int genus : 2; };
ビット・フィールドの位置合わせ
一連のビット・フィールドが int のサイズいっぱいにならない場合は、 埋め込みが行われます。 埋め込みの量は、構造体メンバーの位置合わせ特性によって決定されます。
以下の例は、埋め込みを表しており、すべてのインプリメンテーションで有効です。 int は、4 バイトを占めると想定します。 例では、ID kitchen を、struct on_off 型になるように宣言します。
struct on_off { unsigned light : 1; unsigned toaster : 1; int count; /* 4 bytes */ unsigned ac : 4; unsigned : 4; unsigned clock : 1; unsigned : 0; unsigned flag : 1; } kitchen ;
構造体 kitchen には、合計 16 バイトの 8 つのメンバーが含まれます。
次の表に、各メンバーが占有するストレージを記述します。
メンバー名 | 占有されるストレージ |
---|---|
light | 1 ビット |
toaster | 1 ビット |
(埋め込み -- 30 ビット) | 次の int 境界まで |
count | int のサイズ (4 バイト) |
ac | 4 ビット |
(名前なしフィールド) | 4 ビット |
clock | 1 ビット |
(埋め込み -- 23 ビット) | 次の int 境界まで (名前なしフィールド) |
flag | 1 ビット |
(埋め込み -- 31 ビット) | 次の int 境界まで |
構造体フィールドに対するすべての参照は、完全修飾されている必要があります。 例えば、toaster によって、2 番目のフィールドを参照することは できません。このフィールドを参照するには、kitchen.toaster を 使用しなければなりません。
次の式では、light フィールドを 1 に セットします。
kitchen.light = 1;
ビット・フィールドに範囲外の値を割り当てると、ビット・パターンは保存され、 適切なビットが割り当てられます。 次の式では、kitchen 構造体の toaster フィールドに 0 を割り当てます。 これは、最下位桁のビットのみが toaster フィールドに割り当てられるからです。
kitchen.toaster = 2;
関連参照