ビットフィールド
提供: cppreference.com
明示的なビット単位の幅付きでメンバを宣言します。 隣接するビットフィールドメンバが同じバイトを共有するためにパックされたり、複数のバイトにまたがったりすることがあります。
ビットフィールド宣言は、以下の宣言子を使用する、構造体または共用体のメンバの宣言です。
identifier(オプション) : width
|
|||||||||
| identifier | - | 宣言中のビットフィールドの名前。 名前は省略可能です。 名前のないビットフィールドは指定されたビット数のパディングを導入します。 |
| width | - | ゼロ以上かつベースとなる型のビット数以下の値の整数定数式。 ゼロより大きいときは、そのビットフィールドが占めるビット数です。 ゼロは名前のないビットフィールドでのみ使用でき、そのクラス定義内の次のビットフィールドが確保単位境界から始めることを指定するという、特別な意味を持ちます。 |
説明
ビットフィールドは以下の4つの型のいずれかにのみできます (const または volatile 修飾はしても構いません)。
unsigned int。 符号なしビットフィールド用。 (unsigned int b:3;は 0〜7 の値を保持できます)signed int。 符号付きビットフィールド用。 (signed int b:3;は -4〜3 の値を保持できます)int。 符号の有無が処理系定義であるビットフィールド用。 これはintの通常の意味 (「signed int」と同等) と異なることに注意してください。 (int b:3;は 0〜7 または -4〜3 のいずれかの値を保持できます)_Bool。 1ビットのビットフィールド用。 (bool x:1;は 0〜1 の値を持ち、ブーリアン変換のルールに従って暗黙の変換が行われます)
追加の処理系定義の型が使用できることもあります。 ビットフィールドにアトミック型が使えるかどうかも処理系定義です。 (C11以上) ビットフィールドのビット数 (width) は保持できる値の範囲を制限します。
Run this code
#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
}
隣接する複数のビットフィールドは一緒にパックされることがあります (通常、パックされます)。
Run this code
#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 がゼロの無名ビットフィールドはパディングを分断します。 これは次のビットフィールドが次の確保単位の先頭から始めることを指定します。
Run this code
#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以上) では使用できません。
ノート
ビットフィールドの以下の性質は未定義です。
- ビットフィールドに対して offsetof を呼んだときの効果。
ビットフィールドの以下の性質は未規定です。
- ビットフィールドが保持する確保単位のアライメント。
ビットフィールドの以下の性質は処理系定義です。
int型のビットフィールドが符号付きか符号なしか。- int、 signed int、 unsigned int、および _Bool 以外の型が使用できるかどうか。
- アトミック型が使用できるかどうか。
- ひとつのビットフィールドが確保単位境界をまたがることがあるかどうか。
- 確保単位内のビットフィールドの順序 (ビットフィールドはプラットフォームによって左から右にパックされたり右から左にパックされたりします)。
_Bool のオブジェクト表現のビット数は少なくとも CHAR_BIT ですが、 _Bool 型のビットフィールドの width は1より大きくできません。
C++ では、ビットフィールドの幅はベースとなる型の幅を超えることができます。
参考文献
- C11 standard (ISO/IEC 9899:2011):
- 6.7.2.1 Structure and union specifiers
- C99 standard (ISO/IEC 9899:1999):
- 6.7.2.1 Structure and union specifiers
- C89/C90 standard (ISO/IEC 9899:1990):
- 3.5.2.1 Structure and union specifiers
関連項目
ビットフィールド の C++リファレンス
|