コンパイラは通常、ビットフィールドを1つのワードにまとめる傾向があるため、構造体の全体的なサイズが小さくなります。このパッキングは、ビットフィールドメンバーへのアクセスが遅くなるという犠牲を払っています。例えば:
struct Bitfields
{
unsigned int eight_bit : 8;
unsigned int sixteen_bit : 16;
unsigned int eight_bit_2 : 8;
};
として梱包される可能性があります
0 8 24
-----------------------------------------------------
| eight_bit | sixteen_bit | eight_bit_2 |
-----------------------------------------------------
アクセスするたびにsixteen_bit
、シフトとビット単位の演算が発生します。
一方、あなたがそうするなら
struct NonBitfields
{
uint8_t eight_bit;
uint16_t sixteen_bit;
uint8_t eight_bit_2;
};
次に、コンパイラは通常、メンバーを単語の境界に揃え、次のようにレイアウトします。
0 8 16 24
-----------------------------------------------------
| eight_bit | | sixteen_bit |
-----------------------------------------------------
| eight_bit_2| |
-----------------------------------------------------
これはビットフィールドと比較してより多くのスペースを浪費しますが、メンバーはビットシフトとマスキングなしでより速くアクセスできます。
その他の違いは次のとおりです。
sizeof
ビットフィールドメンバーには応募できません。
- 参照によってビットフィールドメンバーを渡すことはできません。
移植性に関しては、どちらのオプションも標準に準拠したコンパイラで機能するはずです。構造体をファイルまたはソケットに書き出すときに異なるプラットフォーム間のバイナリ移植性を意味する場合、どちらの場合もすべての賭けは無効になります。
好みの点では、uint16_t
スペースを節約するためにフィールドをまとめる正当な理由がない限り、ビットフィールドの代わりに使用することを選択します。構造体の中に多くbool
のsがある場合は、通常、ビットフィールドを使用して、これらのブールフラグを同じ単語にまとめて圧縮します。