Namespaces
Variants

Bit-fields

From cppreference.net

明示的なビット幅を持つメンバーを宣言します。隣接するビットフィールドメンバーは、個々のバイトを共有し、またまたがるようにパックされる場合があります。

ビットフィールド宣言は、以下の struct または union メンバー宣言であり、次の 宣言子 を使用します:

識別子  (オプション) :
identifier - 宣言されるビットフィールドの名前。名前は任意:無名ビットフィールドは指定されたビット数のパディングを導入する
width - ゼロ以上かつ基底型のビット数以下の整数 定数式 。ゼロより大きい場合、このビットフィールドが占有するビット数となる。値ゼロは無名ビットフィールドにのみ許可され、特別な意味を持つ:クラス定義内の次のビットフィールドが割り当て単位の境界から開始することを指定する。

目次

説明

ビットフィールドは以下の(場合によっては const 修飾または volatile 修飾された)型のうち1つのみを持つことができます:

  • unsigned int , 符号なしビットフィールド用(例: unsigned int b : 3 ; の範囲は [ 0 , 7 ]
  • signed int , 符号付きビットフィールド用( signed int b : 3 ; の範囲は [ - 4 , 3 ]
  • int , 実装定義の符号付き/符号なしを持つビットフィールド用(このキーワードの意味は他のすべての場所での「signed int」を意味する int とは異なることに注意)。例えば、 int b : 3 ; の値の範囲は [ 0 , 7 ] または [ - 4 , 3 ] となる可能性がある。
  • _Bool は、1ビットのビットフィールド(例: bool x : 1 ; )に対して範囲 [ 0 , 1 ] を持ち、それとの間の 暗黙変換 はブーリアン変換規則に従います。
(C99以降)
  • ビット精度整数型(例: _BitInt ( 5 ) : 4 ; は範囲 [ - 8 , 7 ] を持ち、 unsigned _BitInt ( 5 ) : 4 ; は範囲 [ 0 , 15 ] を持ちます)。
(C23以降)

追加の実装定義型が許容される可能性があります。 ビットフィールドが atomic 型を持つことができるかどうかも実装定義です。 (C11以降) ビットフィールドのビット数( width )は、保持できる値の範囲の上限を設定します:

#include <stdio.h>
struct S
{
    // 3ビット符号なしフィールド、
    // 許容値は0...7
    unsigned int b : 3;
};
int main(void)
{
    struct S s = {7};
    ++s.b; // 符号なしオーバーフロー
    printf("%d\n", s.b); // 出力: 0
}

複数の隣接するビットフィールドは、(通常は)まとめてパックすることが許可されています:

#include <stdio.h>
struct S
{
    // 通常4バイトを占有:
    // 5ビット: b1の値
    // 11ビット: 未使用
    // 6ビット: b2の値
    // 2ビット: b3の値
    // 8ビット: 未使用
    unsigned b1 : 5, : 11, b2 : 6, b3 : 2;
};
int main(void)
{
    printf("%zu\n", sizeof(struct S)); // 通常4を表示
}

特別な 名前のないビットフィールド width をゼロにすると、パディングを分割します:これは次のビットフィールドが次の割り当て単位の先頭から始まることを指定します:

#include <stdio.h>
struct S
{
    // 通常8バイトを占有:
    // 5ビット: b1の値
    // 27ビット: 未使用
    // 6ビット: b2の値
    // 15ビット: b3の値
    // 11ビット: 未使用
    unsigned b1 : 5;
    unsigned    : 0; // 新しいunsigned intを開始
    unsigned b2 : 6;
    unsigned b3 : 15;
};
int main(void)
{
    printf("%zu\n", sizeof(struct S)); // 通常8を出力
}

ビットフィールドは必ずしもバイトの先頭から始まるわけではないため、ビットフィールドのアドレスを取得することはできません。ビットフィールドへのポインタは不可能です。ビットフィールドは sizeof および _Alignas (C11以降) (C23以前) alignas (C23以降) (C11以降) と共に使用することはできません。

注記

以下のビットフィールドの使用法は 未定義動作 を引き起こします:

  • offsetof をビットフィールドに対して呼び出すこと。

ビットフィールドの以下のプロパティは 未規定 です:

  • ビットフィールドを保持する割り当て単位のアライメント。

ビットフィールドの以下のプロパティは 実装定義 です:

  • int 型のビットフィールドが符号付きとして扱われるか符号なしとして扱われるか。
  • int signed int unsigned int _Bool (C99以降) および(場合によっては unsigned _BitInt ( N ) (C23以降) 以外の型が許可されるかどうか。
  • アトミック型が許可されるかどうか。
(C11以降)
  • ビットフィールドが割り当て単位の境界を跨ぐことができるかどうか。
  • 割り当て単位内でのビットフィールドの順序(一部のプラットフォームではビットフィールドは左から右にパックされ、他のプラットフォームでは右から左にパックされます)。

_Boolのオブジェクト表現におけるビット数は少なくとも _Bool であるにもかかわらず、 CHAR_BIT 型のビットフィールドの width _Bool を超えることはできません。 1

(C99以降)

C++プログラミング言語において、ビットフィールドの幅は基底型の幅を超えることができます(ただし、追加のビットはパディングビットです)。また、型 int のビットフィールドは常に符号付きです。

参考文献

  • C23規格 (ISO/IEC 9899:2024):
  • 6.7.2.1 構造体及び共用体指定子
  • C17規格 (ISO/IEC 9899:2018):
  • 6.7.2.1 構造体及び共用体指定子
  • C11規格 (ISO/IEC 9899:2011):
  • 6.7.2.1 構造体及び共用体指定子
  • C99標準 (ISO/IEC 9899:1999):
  • 6.7.2.1 構造体および共用体指定子
  • C89/C90標準 (ISO/IEC 9899:1990):
  • 3.5.2.1 構造体および共用体指定子

関連項目

C++ documentation for Bit-field