ビットフィールドは、CおよびC ++構造体をしっかりとパックしてサイズを縮小します。これは苦労しないように見えます。メンバーのビット数を指定し、コンパイラはビットを混同します。この制限は、ビットフィールドメンバのアドレスを取ることができないことである。これは、ビットフィールドメンバが混在して格納されているからである。 sizeof()
も禁止されています。
ビットフィールドのコストは、メンバー値を抽出または変更するためにメモリを取得し、ビット単位の操作を適用する必要があるため、アクセスが遅くなります。これらの操作は、実行可能なサイズにも追加されます。
ビット演算はどれくらいの費用がかかりますか?単純な非ビットフィールド構造を仮定します。
struct foo {
unsigned x;
unsigned y;
}
static struct foo my_var;
後のコードでは、
my_var.y = 5;
sizeof (unsigned) == 4
場合、xは構造体の先頭に格納され、yは4バイトに格納されます。生成されるアセンブリコードは次のようになります。
loada register1,#myvar ; get the address of the structure
storei register1[4],#0x05 ; put the value '5' at offset 4, e.g., set y=5
これは、xがyと混同されていないため、簡単です。しかし、ビットフィールドを使って構造体を再定義すると想像してください:
struct foo {
unsigned x : 4; /* Range 0-0x0f, or 0 through 15 */
unsigned y : 4;
}
x
とy
両方に4ビットが割り当てられ、1バイトを共有します。したがって、構造体は8ではなく1バイトを占有しますy
上限に設定したと仮定してアセンブリをy
と設定します。
loada register1,#myvar ; get the address of the structure
loadb register2,register1[0] ; get the byte from memory
andb register2,#0x0f ; zero out y in the byte, leaving x alone
orb register2,#0x50 ; put the 5 into the 'y' portion of the byte
stb register1[0],register2 ; put the modified byte back into memory
これらの構造が数千ないし数百万ある場合、これは良いトレードオフになる可能性があり、キャッシュにメモリを保持したり、スワッピングを防止したり、実行可能ファイルを膨らませてこれらの問題を悪化させたり、すべてのことと同様に、良い判断をしてください。
デバイスドライバの使用:デバイスドライバの賢明な実装方法としてビットフィールドを使用しないでください。ビットフィールドの格納レイアウトはコンパイラ間で必ずしも一貫しているわけではなく、そのような実装は移植性がありません。設定値へのリード・モディファイ・ライトは、予期しない動作を引き起こすデバイスが予期しない動作をする可能性があります。