データ構造アライメント
キャッシュメモリのラインに合わせてメモリを割り当てることは有益である。配列が複数のスレッドが動作するようにパーティション化されている場合、サブ配列の境界をキャッシュラインとアラインさせないとパフォーマンスが低下する可能性がある。次に、64バイトのキャッシュにアライメントされたメモリ(サイズ10の倍精度配列)の例を示す。
上記の例では、FinalPadShort 構造体のサイズ sizeof(FinalPadShort) は5や8ではなく6(shortのアライメントの倍数)になる。
構造体メンバの順序を変更したり、構造体メンバのコンパイラのアライメントを変更(パッキング)して、必要なメモリを減らす(または既存の形式に準拠させる)ために、構造体のアライメントを変更することができる。前述の MixedData 構造体にこれを適用すると、次のようになる。
これにより、構造体のコンパイル後のサイズが、メンバのバイト数を単純に合計したサイズである8バイトと一致するようになった。Padding1[1] は Data4 によって置き換えられ(従って排除され)、構造体は既にlong wordのサイズにアラインされているので、 Padding2[3] はもはや必要ではない。
MixedData 構造体を1バイト境界にアライメントさせる別の方法は、プリプロセッサに構造体メンバの所定のアライメントを破棄させ、これによりパディングバイトを挿入しないようにすることである。
C11およびC++11よりも前の規格では、構造体メンバのアライメントを定義する標準的な方法はないが、コンパイラの中には #pragma ディレクティブを使用してソースファイル内のパッキングを指定するものがある。次にその例を示す。
この構造体は、32ビットシステムで6バイトのコンパイルサイズを持つ。上記のディレクティブは、Microsoft、Borland、GNUなどのコンパイラで利用できる。
もう1つの例:
long double(C++ BuilderとDMCでは10バイト、Visual C++では8バイト、GCCでは12バイト) - C++ Builderでは8バイトアライメント、DMCでは2バイトアライメント、Visual C++では8バイトアライメント、GCCでは4バイトアライメント
ポインタ(4バイト) - 4バイトアライメント
LP64モデルの64ビットシステムは次の通りである。
long(8バイト) - 8バイトアライメント
double(8バイト) - 8バイトアライメント
long long(8バイト) - 8バイトアライメント
long double(GCCでは16バイト) - GCCでは16バイトアライメント
ポインタ(8バイト) - 8バイトアライメント
一部のデータ型は実装に依存する。
次に挙げる構造体は、様々な型のメンバを有しており、そのバイト数を単純に合計すると8バイトになる。
コンパイル後、構造体にはパディングバイトが追加され、各メンバの適切なアライメントが保証される。
構造体のコンパイルされたサイズは12バイトになる。最後のメンバの後にもパディングバイトが追加されていることに留意されたい。この場合、構造体の合計サイズは、構造体メンバの最大のアライメントの倍数となる。上の例では、構造体を12バイトのサイズにパディングするために最後のメンバの後に3バイトが追加される。
上記の例では、sizeof演算子により算出される FinalPad 構造体のサイズ sizeof(FinalPad) は5ではなく8(floatのアライメントの倍数)になる。