C言語のビットフィールド(bit fields)は、標準の型サイズの代わりに指定されたビット数を占有する構造体のメンバーです。特にフラグやコンパクトな状態セットを保存するためにメモリを節約することができます。
宣言:
struct Flags { unsigned int enable : 1; unsigned int mode : 2; unsigned int code : 5; };
この例では、構造体は最小8ビットであり、3 * sizeof(unsigned int)ではありません。
適用する場所:
制限と落とし穴:
例:
struct Packet { unsigned char start : 1; unsigned char id : 3; unsigned char flag : 4; };
質問: char または signed int 型をビットフィールドに使用することはできますか?
回答: C言語標準では、int、unsigned int、および(コンパイラの拡張によって)他の標準整数型(char、short)を使用することが許可されています。ただし、移植性はintおよびunsigned intのみで保証されています。
エラーの例:
struct Example { signed char a : 3; }; // 異なるコンパイラ/アーキテクチャでは符号とビットの順序の保存ルールが異なる。
物語
ARMとx86でのソフトウェア統合中に、ビットフィールドを持つ構造体が異なる方法でアンパックされることが判明しました:異なるビット順序とアライメント。これらの違いを考慮せずに設計したため、クロスプラットフォーム環境でデータを読み取ることができなくなりました。
物語
モーターコントローラの制御システムで、ビットフィールド構造体に誤って
char型が使用されました。一部のARMプロセッサでは、符号の拡張が不正確であり、フラグの誤った処理につながりました。
物語
ネットワークプロトコルでメッセージフラグをパックするためにビットフィールドを使用しましたが、初期化されていない高位ビットフィールドがゴミであることを考慮しませんでした。デバイス間の送信時に初期化の違いにより、ランダムな状態のエラーが発生しました。