ビットフィールド

出典: フリー百科事典『ウィキペディア(Wikipedia)』
移動: 案内検索

ビットフィールド (: bit field) は、プログラミングにおいてブーリアン型フラグをコンパクトなビットの並びとして格納する手法である。ビットフィールドの格納には、整数型を使用する。個々のフラグは、ビット単位で格納される。通常は、ソースコードで、個別のビットがフラグに対応する意味を付けられた、2の冪乗の定数が定義される。ビット演算論理積論理和否定の組み合わせが、フラグのセット・リセットとテストを行うために使われる。

ビットフィールドはビット配列とは異なる。ビット配列は、整数でインデックスを付けられた大きなビットの集合を保存するために使用され、コンピュータ言語でサポートされる整数型よりも大きいことがある。ビットフィールドは典型的にはワードサイズの範囲内であり、ビットの表示は数値によるインデックスから独立している。ビットフィールドは、それぞれのフラグのビットインデックスが列挙型の値のビット配列を使用することで、安全かつシンプルで、高速に動作する実装となる。

[編集]

C言語での実装例:

#define KEY_UP       (1 << 0)
#define KEY_RIGHT    (1 << 1)
#define KEY_DOWN     (1 << 2)
#define KEY_LEFT     (1 << 3)
#define KEY_BUTTON1  (1 << 4)
#define KEY_BUTTON2  (1 << 5)
 
int gameControllerStatus = 0;
 
void keyPressed(int key) {
     gameControllerStatus |= key;
}
 
void keyReleased(int key) {
    gameControllerStatus &= ~key;
}
 
int isPressed(int key) {
    return gameControllerStatus & key;
}

2の冪乗を表すためにハードコードされた数値(0x08)を使用する代わりに、ビットシフト演算子を使用した表現を使用すると、ビットマスクを示すものであるというプログラマの意図が明確になり、可読性の観点からすると望ましい。

カーニハンリッチーの本、プログラミング言語Cでは、直接フィールドを定義し、アクセスする方法が記述されている。この方法を使用することで、ビット演算子が不要となり、ビットメンバに構造体メンバと同じようにアクセスすることができる。 structを使用した例:

struct preferences {
    unsigned int likes_ice_cream : 1;
    unsigned int plays_golf : 1;
    unsigned int watches_tv : 1;
    unsigned int reads_books : 1;
}; 
 
struct preferences fred;
 
fred.likes_ice_cream = 1;
fred.plays_golf = 1;
fred.watches_tv = 1;
fred.reads_books = 0;
 
if (fred.likes_ice_cream == 1)
    /* ... */

構造体のビットメンバは実用上は欠点がある。まず、メモリ上のビットの順序コンパイラによって変化する。加えて、多くの一般的なコンパイラは、ビットメンバの読み書きに対して、非効率なコードを生成する。さらに、ビットフィールドに関しては(特にマルチプロセッサシステムの場合は)、潜在的なスレッドセーフの問題がある。ほとんどのCPUではメモリ上の任意のビットの集合を扱えず、代わりにワード全体をロード/ストアする必要があるためである。以下のコード例はミューテックスを使用したとしても、スレッドセーフではない:

struct foo {
    int flag : 1;
    int counter : 15;
};
 
struct foo my_foo;
 
/* ... */
 
pthread_mutex_lock(&my_mutex);
my_foo.flag = !my_foo.flag;
pthread_mutex_unlock(&my_mutex);
 
/* 他のスレッド */
my_foo.counter += 1;

ほとんどのCPUでは、flagcounterを別々にロードしてストアすることは、ハードウェアレベルで不可能である。(これがスレッドセーフであるためには、counter自身がスレッドセーフである必要がなくても、flagcounter両方について、全てのアクセスの前後でミューテックスをロック・アンロックする必要がある。)同様に、ビット順序の問題ため、ビットフィールドが正確にワードサイズの構造である依存性がある。

関連項目[編集]

外部リンク[編集]