ビットフィールド
ビット領域を定める
あまり見かけられませんが、構造体にはビットフィールドと呼ばれる技術があります
これは、ひとつのメモリ領域(バイト単位)に名前をつけてビット単位に振り分けるものです
たとえば、4ビットの領域を持つ変数を作成することはできませんでした
char型でも1バイトですね
Unicodeへの変換プログラムなどでは2バイトの領域を持つ変数があると便利そうです(たぶん…)
このように、プログラマ側で変数の領域を定めたい時にビットフィールドは有効です
ビットフィールドの作成は、構造体の生成とほぼ同じです
ビットフィールドで使われる方は、通常intまたはunsignedです(signedの場合は上位ビットが符合に使われます)
型 名前: サイズ;
型は説明したとおりです
名前にはメンバ名同様に、このビット領域の名前を指定します
サイズにはビット領域を指定します。3と指定すれば、この名前の領域に3ビット割り当てられます
このような特徴から、ビットフィールドは特定のビット数で確実に表現できる情報に用いられたりします
たとえば、boolean型の変数の作成などにはビットフィールドが有効です
1ビットの変数を生成しておけば、確実に0か1しか入りません
#include <stdio.h>
struct {
unsigned bool: 1;
}Boolean;
int main() {
Boolean.bool = 2;
printf("2 = %d\n" , Boolean.bool);
Boolean.bool = 3;
printf("3 = %d" , Boolean.bool);
return 0;
}
結果は次のようになりました
2 = 0
3 = 1
この結果で、boolが1ビットまでの領域しか確保されていないことがわかります
1ビットということは、2進数で一桁の情報です
2進数の1桁が格納できる情報量は一意で2つまでです
つまり、trueかfalse(真か偽)しかないブール型を制御する変数にうってつけですよね
10進数の2は2進数で10です
10を代入しても、1ビットが表現できるのは 0 〜 1 までのため
それ以降の上位ビットは破棄されるのです
Boolean.bool = 0000 0010;
Boolean.bool = 0000 0011;
上位7ビットはオーバーフローによって破棄され先の結果が得られたのです
ビットフィールドによって、代入できる値を制限して不要なエラーを避けられます
ただし、ビットフィールド自体は1ビットでも
構造体変数はunsigned(通常は4バイト)の領域であるということに注意してください
先ほどのプログラムのビットフィールドは、そのうちの1ビットなのです
<---------unsigned(4バイト)------------>
|
---|
<--bool(1ビット)--> | <----空き領域---->
|
---|
もちろん、ビットフィールドはひとつの構造体に任意の数を生成することができます
ビットフィールドが使われている構造体に、通常のメンバを宣言することも可能です
#include <stdio.h>
struct {
char *str;
unsigned code: 4;
unsigned bool: 1;
}obj;
int main() {
obj.str = "kitty on your lap";
obj.code = 0xFF;
printf("%d" , obj.code);
return 0;
}
このプログラムの場合は、次のような関係になっています
<---------unsigned(4バイト)------------>
|
---|
<--code(4ビット)--> | <--bool(1ビット)--> | <----空き領域---->
|
---|
ビットフィールドは、C言語プログラムであまり多用されることはありません。が
特殊なデータ型を扱う変数の生成に活用したり
不用意なデータの代入で起こるエラーを未然に防ぐことが可能です
上手に使い分けましょう