コンパイラーが32ビットシステムと64ビットシステムで異なるパディングを使用するかどうか疑問に思っていたので、以下のコードを単純なVS2019 C++コンソールプロジェクトで記述しました。
struct Z
{
char s;
__int64 i;
};
int main()
{
std::cout << sizeof(Z) <<"\n";
}
各「プラットフォーム」設定で期待したこと:
x86: 12
X64: 16
実結果:
x86: 16
X64: 16
X86のメモリワードサイズは4バイトであるため、i
のバイトを2つの異なるワードに格納する必要があります。だから私はコンパイラがこのようにパディングするだろうと思った:
struct Z
{
char s;
char _pad[3];
__int64 i;
};
これの背後にある理由は何ですか?
パディングはワードサイズではなく、各データタイプの アラインメント によって決定されます。
ほとんどの場合、配置要件は型のサイズと同じです。したがって、int64
のような64ビットタイプの場合、8バイト(64ビット)の配置になります。型のストレージが正しく配置されたアドレスに到達するように、構造体にパディングを挿入する必要があります。
ポインター型など、両方のアーキテクチャーで異なるサイズの組み込みデータ型を使用すると、32ビットと64ビットのパディングに違いが見られる場合があります( int*
)。
これは パディングと構造体メンバーの配置 で指定されているデータ型の配置要件の問題です。
すべてのデータオブジェクトには、alignment-requirementがあります。 構造体、共用体、および配列を除くすべてのデータの配置要件は、オブジェクトのサイズまたは現在のパッキングサイズです(
/Zp
またはpackプラグマのいずれか小さい方)。
また、構造体メンバーの配置のデフォルト値は / Zp(構造体メンバーの配置) で指定されています
次の表に、使用可能なパッキング値を示します。
/
Zp
引数効果
1 1バイト境界で構造をパックします。/Zpと同じです。
2 2バイト境界で構造をパックします。
4 4バイト境界に構造をパックします。
8 8バイト境界に構造体をパックします(x86、ARM、およびARM64のデフォルト)。
16バイトの構造を16バイト境界にパックします(x64のデフォルト)。
X86のデフォルトは8バイトの/ Zp8なので、出力は16です。
ただし、/Zp
オプションで別のパッキングサイズを指定できます。
これは ライブデモ と/Zp4
を使用したもので、出力が16ではなく12になります。