第16章 ビットフィールド
16.1 ビットフィールドの機能
ビットフィールドは整数型変数をビット単位で操作できるようにする。
 
16.2 ビットフィールドの記述
/* ビットフィールドの定義 */
ビットフィールドの記述方法は構造体に準じます。
定義時のメンバの記述方法だけが異なります。
定義後の、変数宣言や、メンバアクセス方法などはみな同じです。
ビットフィールドのメンバは、
型 メンバ名:ビット幅;
のように指定します。
型としては通常、unsigned int型が使用されます。
ビットを論理的に操作するだけなのでunsignedが適しています。
次の例は、1ビットでon/off処理するフラグを4つ、
3ビットの情報を使うデータをひとつ用意したビットフィールドです。
struct Bisset {
unsigned int busy:1;
unsigned int ready:1;
unsigned int send:1;
unsigned int rec:1;
unsigned int status:3;
};
Bitset bst; // そのBitset型の変数bstを宣言
この記述でメンバ宣言である
unsigned int busy : 1;
は1ビットのunsigned int型をもつbusyというメンバを宣言するという意味になります。
statusは3ビットを確保しているので、0~7の値を表現できます。
/* 語境界の指定 */
ビットフィールドで指定されたビット数が全部合算してもint型ひとつで済むなら、
それはひとつのint領域に格納されます。
もし1個のint型に入らないときは、ふたつの語にまたがって格納されます。
それは適切に行われますが、意図的に境界指定をすることもできます。
それには、
名前なしでビット幅0
という特別のメンバを使います。
次に例を示します。
struct smpbit {
unsigned int dt1:3; // 最初のint領域に格納される
unsigned int dt2:1; // 最初のint領域に格納される
unsigned int dt3:5; // 最初のint領域に格納される
unsigned int dt3:6; // 最初のint領域に格納される
unsigned int    :0; // これで強制的に語境界を作る
unsigned int dt4:5; // 次のint領域に格納される
unsigned int dt5:1; // 次のint領域に格納される
unsigned int dt6:2; // 次のint領域に格納される
};
/* 無名ビットフィールド */
1語の中で、ビット位置が指定されていて、それを守らなければならない
といったケースで使用します。
たとえば与えられた仕様書に、次のようなビット位置指定が行われていたとします。
0 未使用
1 busy
2 ready
3 未使用
4 未使用
5 未使用
6 send
7 rec
8 status
9 status
10 status
これを表現するには未使用のところを位置調整しなければなりません。
そのためにはビット位置0,3,4,5のパディングが必要です。
実際にこれを記述するにはダミーのメンバ名を使うのも方法ですが、
名前なしでビット幅あり // 無名ビットフィールド
のように無名ビットフィールドを指定するのが簡単です。
上の仕様書を実現する記述は次のようになります。
struct Bitset {
unsigned int :1 // 1ビットパディング(未使用にする)
unsigned int busy :1
unsigned int ready :1
unsigned int :3 // 3ビットパディング(未使用にする)
unsigned int send :1
unsigned int rec :1
unsigned int status :3
};
/* ビットフィールドのメンバ参照 */
Bitset bst, *bp = &bst;
bst.send = 1; // ビットフィールド実体の場合
bp->send = a; // ビットフィールドを指すポインタの場合
/* 構造体とビットフィールドの混在 */
16_16-1