アラインメントの重要性は、主にパフォーマンスと移植性を表しています。使用しているプラットフォームのアライメント要件を理解していない場合、コードをそこで実行できるとは限らないか、誰かがそのプラットフォームに適切にアライメントされていないコード(またはデータ)を移動するとすぐに壊れてしまう可能性があります。
ハードウェアやOSなどに応じて、これの一部は自動的に処理されますが、アライメントルールを破るとペナルティが発生します。デフォルトでは、古いバージョンのWindowsは、アライメント障害が発生した場合にプロセスをクラッシュさせていましたが、現在、Windowsは回復できますが、CPUサイクルが追加されます。
整列属性は、整列を強制するGCC固有の機能です(C言語とは関係ありません)。整列とは、データをメモリに配置する必要のある数値の倍数です。次に、コンパイラーはデータ構造にガベージを挿入して、コンパイラーに課した制約が満たされていることを確認します。
あなたの質問の例を見てみましょう:
struct data
{
int a __attribute__( ( aligned ( 8 ) ) ) ;
char ch __attribute__( ( aligned ( 1 ) ) ) ;
float s __attribute__( ( aligned ( 4 ) ) ) ;
} ;
この場合、架空のプラットフォームのネイティブサイズint
とネイティブサイズの両方が4バイトであると想定します。float
メモリに配置された最終的な構造体は、より近くなります
struct data
{
int a; // 0x00
int junk0 // 0x04
char ch; // 0x08
char junk1[3] // 0x09
float s; // 0x0C
} ;
コンパイラが最初の整数をパディングするかどうかはわかりません。そのため、実際には最終的な構造体で8バイトを占有します。パディングだけで64ビットになるわけではありません。構造体は64ビットアドレスにのみ配置されると想定されるため、奇妙だと思います。したがって、32ビットアーキテクチャでは、メモリを割り当てる場合は、そのメモリが8の倍数であるアドレスに整列されていることはこれでOKです。たぶんそれはそれをよりポータブルにし、32ビットと64ビットで同じように動作することを確認するためです。
コンパイラーは、より積極的になり、実際にはより多くのスペースを浪費することを選択できますが、それに対抗するためのパックディレクティブがあります。ネイティブバイナリ互換性があなたにとって本当に重要であるなら、これらのことは本当に重要です。