名前空間
変種
操作

ビットフィールド

From cppreference.com
< c‎ | language

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

ビットフィールド宣言は、以下のデクラレータを使用する構造体または共用体のメンバ宣言です。

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

目次

[編集] 解説

ビットフィールドは、以下のいずれかの型(const または volatile 修飾子が付いていてもよい)のみを持つことができます。

  • unsigned int、符号なしビットフィールドの場合(例: unsigned int b : 3; は範囲 [07]
  • signed int、符号付きビットフィールドの場合(signed int b : 3; は範囲 [-43]
  • int、実装定義の符号性を指定するビットフィールドの場合(他のすべての場所でキーワード int が「signed int」を意味するのとは異なることに注意)。たとえば、int b : 3; は、範囲 [07] または [-43] の値を持つことがあります。
  • _Bool、1ビットビットフィールドの場合(例: bool x : 1;)は範囲 [01] を持ち、ブール変換規則に従って暗黙的な変換が行われます。
(C99以降)
  • ビット単位の整数型(例: _BitInt(5) : 4; は範囲 [-87] を持ち、unsigned _BitInt(5) : 4; は範囲 [015] を持ちます)。
(C23以降)

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

#include <stdio.h>
 
struct S
{
    // three-bit unsigned field,
    // allowed values are 0...7
    unsigned int b : 3;
};
 
int main(void)
{
    struct S s = {7};
    ++s.b; // unsigned overflow
    printf("%d\n", s.b); // output: 0
}

複数の隣接するビットフィールドは、一緒にパックされることが許可されており(通常はそうされます)。

#include <stdio.h>
 
struct S
{
    // will usually occupy 4 bytes:
    // 5 bits: value of b1
    // 11 bits: unused
    // 6 bits: value of b2
    // 2 bits: value of b3
    // 8 bits: unused
    unsigned b1 : 5, : 11, b2 : 6, b3 : 2;
};
 
int main(void)
{
    printf("%zu\n", sizeof(struct S)); // usually prints 4
}

幅ゼロの特殊な*Unnamed bit-field*はパディングを中断します。これは、次のビットフィールドが次のアロケーションユニットの先頭から開始されることを指定します。

#include <stdio.h>
 
struct S
{
    // will usually occupy 8 bytes:
    // 5 bits: value of b1
    // 27 bits: unused
    // 6 bits: value of b2
    // 15 bits: value of b3
    // 11 bits: unused
    unsigned b1 : 5;
    unsigned    : 0; // starts a new unsigned int
    unsigned b2 : 6;
    unsigned b3 : 15;
};
 
int main(void)
{
    printf("%zu\n", sizeof(struct S)); // usually prints 8
}

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

[編集] 注意

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

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

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

  • ビットフィールドを含むアロケーションユニットのアライメント。

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

  • int 型のビットフィールドが符号付きとして扱われるか、符号なしとして扱われるか。
  • intsigned intunsigned int_Bool(C99 以降)、および(unsigned かもしれない)_BitInt(N)(C23 以降)以外の型が許可されるかどうか。
  • アトミック型が許可されるかどうか。
(C11 以降)
  • ビットフィールドがアロケーションユニットの境界をまたぐことができるかどうか。
  • アロケーションユニット内のビットフィールドの順序(プラットフォームによっては、ビットフィールドは左から右へ、あるいは右から左へパックされます)。

_Bool のオブジェクト表現のビット数は少なくとも CHAR_BIT ですが、_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++ ドキュメント (ビットフィールド)
English 日本語 中文(简体) 中文(繁體)