
ソース: http://geeksforgeeks.org/?p=9705
要約すると、アライメントを犠牲にすることなく、ビットのパッキング(ビットフィールドの目的)を可能な限り最適化しています。
変数のデータ配置は、これらのバンクにデータが格納される方法を扱います。たとえば、32 ビット マシンでの int の自然なアラインメントは 4 バイトです。データ型が自然にアラインされている場合、CPU は最小の読み取りサイクルでそれをフェッチします。
同様に、 の自然なアラインメントshort int
は 2 バイトです。つまり、short int はバンク 0 – バンク 1 のペアまたはバンク 2 – バンク 3 のペアに格納できます。Adouble
は 8 バイトを必要とし、メモリ バンクで 2 行を占有します。double のアライメントがずれていると、double データをフェッチするために 2 つ以上の読み取りサイクルが強制されます。
double 変数は 32 ビット マシンの 8 バイト境界に割り当てられ、2 つのメモリ読み取りサイクルが必要であることに注意してください。64 ビット マシンでは、バンク数に基づいて、double 変数が 8 バイト境界に割り当てられ、1 回のメモリ読み取りサイクルしか必要としません。
そのため、コンパイラはすべての構造体にアラインメント要件を導入します。構造体の最大のメンバーのようになります。から削除char
してstruct
も、まだ4 バイトになります。
ではstruct
、char
1 バイト アラインされます。その後にビット フィールドが続きint
ます。これは整数用に 4 バイト アラインされていますが、ビット フィールドを定義しました。
8 ビット = 1 バイト。Char
任意のバイト境界にすることができます。したがって、Char
+ Int:8
= 2 バイトです。これは奇妙なバイト境界であるため、コンパイラは 4 バイト境界を維持するためにさらに 2 バイトを追加します。
int
8 バイトにするには、実際の(4 バイト) と(1 バイト)を宣言する必要がありますchar
。それは5バイトです。これも奇妙なバイト境界なので、は8 バイトstruct
にパディングされます。
パディングを制御するために過去によく行ったことは、struct
常に 4 バイトの境界を維持するために、間にフィラーを配置することでした。だから私はstruct
このようなものを持っている場合:
struct s {
int id;
char b;
};
次のように割り当てを挿入します。
struct d {
int id;
char b;
char temp[3];
}
これstruct
により、4 バイト + 1 バイト + 3 バイト = 8 バイトのサイズが得られます。このようにstruct
して、特にネットワーク経由でどこかに送信する場合に、希望どおりにパディングすることができます。また、実装を変更した場合 (これstruct
をバイナリファイルに保存する場合など、フィラーは最初から存在していたので、初期構造を維持している限り、すべて問題ありません!)
最後に、ビットフィールドを使用した C 構造体のサイズに関するこの記事を読んで、詳細を確認してください。