この例を見てください
class A
{
public:
int a;
char b;
int c;
};
すべてのコンパイラ(x86、32、または64ビットの場合)はA
、9ではなく12バイトをクラスに割り当てます。したがって、これらはb
整数境界またはバス境界に整列しています。私の質問は、これがそうするためのC ++標準にあるかどうか、そしてそれをしないコンパイラがあるかどうかです。
C ++標準では、次のように指定されています。
int
幅が4バイトの場合、実装に応じて、1、2、または4バイトの配置が必要です)。public
)はすべて、宣言された順序で割り当てられますしたがって、標準では、クラスのサイズを12バイトにする必要があると正確に規定されていません。
しかし、それはの後に割り当てられるべきであり、それはの後に割り当てられるべきであると言っています。b
a
c
b
int
幅が4バイトで、4バイトのアラインメントが必要なプラットフォームでは、これにより、有効な最小サイズとして12バイトが残ります。
a
最初の4バイトを取りますb
1バイトかかりますc
4バイトが必要ですが、4バイト境界で割り当てる必要があります。b
そのような境界を1バイト超えてc
終了したため、 3バイトのパディングを挿入することにより、次に配置する有効な位置が見つかります。したがって、クラスの合計サイズは、メンバーのサイズ(4 + 1 + 4 = 9)に3バイトのパディングを加えたものになり、合計で12になります。
a, c, b
ここでは効果がない別のルールがありますが、代わりに順序でメンバーを定義した場合は問題になります。
含まれているクラス(A
)は、最も厳密に整列されたメンバーオブジェクトから整列要件を継承します。つまり、が含まれているためint
、と同じ位置合わせ要件がint
あります。a, b, c
また、オブジェクトの合計サイズは配置要件の倍数である必要があるため、メンバーを順番に含むクラスには12バイトのストレージが必要です。b
との間ではなく、3バイトのパディングをクラスの最後にシフトするだけc
です。
ただし、場合によっては、メンバーをサイズの降順で並べ替えると、クラスのサイズが小さくなることがあります。
代わりに、次のようなクラスがあったとします。
class B {
char a;
double b;
int c;
};
これには24バイトのストレージが必要でした(の場合は1バイト、のa
場合は8バイト、のb
場合は4バイトですc
が、b
最終的に8バイトの境界になるようにするには、との間に7バイトのパディングが必要です。クラス全体のサイズは8の倍数になり、の後にさらに4バイトが必要になります。a
b
c
ただし、次のように、サイズに従ってメンバーを並べ替えます。
class B {
double b;
int c;
char a;
};
その結果、クラスは16バイトしか必要としません。
メンバーオブジェクト自体に対して同じ1+4 + 8バイトですが、現在c
はすでに4バイト境界で整列されており(その後b
は8バイト境界で終了するため)、a
整列は必要ないため、整列のみが行われます。必要なのはB
、8の倍数のサイズであることを確認することです。メンバーは13バイトを使用するため、3バイトのパディングを追加でき、クラスは16バイトになり、最初のバージョンより33%小さくなります。
プラグマディレクティブを使用して、コンパイル時に構造パッキングを制御することができます。 #PragmaPackを参照してください
たとえば、次の例では、メンバーを整列せず、メンバーを隣り合わせに配置します。
#pragma pack(push, 1)
struct A4
{
char a;
double b;
char c;
};
#pragma pack(pop)
ここからの例。
GCCはプラグマパックもサポートしています。ディレクティブは一部の標準の一部ではありませんが、多くのコンパイラがそれをサポートしています。
ただし、上記を行う理由はありません。コンパイラーは、メンバーへのアクセスを高速化するためにそれらを調整します。これを変更する理由はありません。
あなたの場合、「b」は常に正しく整列されています。cを32ビット境界に揃えるためにパディングされます。特定の実装の余地はありますが、ほとんどのコンパイラーは、2バイトと4バイトの変数を2バイトと4バイトの境界に揃えるという規則に従います。
32ビットシステムでもdoublesとlongint(8バイト)は4バイト境界に揃えられますが、64ビットシステムでは8バイトに揃えられます。
標準では、コンパイラは必要に応じてより多くのバイトをパディングできます。基本的には、コンパイラではなくホストのアーキテクチャに依存します。
はい、アライメントは規格の至る所で言及されており、主にセクション3.11(アライメント)です。プラットフォームに依存するため、オブジェクトの実際のサイズに依存するプログラムは、本質的に移植性がありません。