5

/Zp フラグを指定せずに、VS2012 の x64 プロジェクトで次のコードをコンパイルすると、次のようになります。

#pragma pack(show)

次に、コンパイラは吐き出します:

value of pragma pack(show) == 16

プロジェクトが Win32 を使用している場合、コンパイラは次のように出力します。

value of pragma pack(show) == 8

私が理解していないのは、Win64 の任意の型 (つまり、long long とポインター) の最大の自然なアラインメントが 8 であるということです。

それに関連して、なぜ /Zp16 を使用するのでしょうか?

編集:

これが私が話していることを示す例です。x64 の場合、ポインターは 8 バイトの自然なアライメントを持っていますが、Zp1 はポインターを強制的に 1 バイト境界にすることができます。

struct A
{
    char a;
    char* b;
}

// Zp16
// Offset of a == 0
// Offset of b == 8

// Zp1
// Offset of a == 0
// Offset of b == 1

ここで、SSE を使用する例を挙げると:

struct A
{
    char a;
    char* b;
    __m128 c; // uses declspec(align(16)) in xmmintrinsic.h
}

// Zp16
// Offset of a == 0
// Offset of b == 8
// Offset of c == 16

// Zp1
// Offset of a == 0
// Offset of b == 1
// Offset of c == 16

__m128 が本当に組み込み型である場合、オフセットは Zp1 で 9 になると予想されます。しかし、xmmintrinsic.h の定義で __declspec(align(16)) を使用しているため、Zp 設定より優先されます。

だからここに私の質問が少し異なって表現されています: 16B の自然な位置合わせを持つが、前の例で 9 のオフセットを持つ 'c' の型はありますか?

4

2 に答える 2

4

ここのMSDN ページには、「x64 のデフォルトの位置合わせを 8 にしない理由は?」という質問に関する次の関連情報が含まれています。

最新のプロセッサ命令を使用するアプリケーションを作成すると、いくつかの新しい制約と問題が発生します。特に、多くの新しい命令では、データを 16 バイト境界に揃える必要があります。さらに、頻繁に使用されるデータを特定のプロセッサのキャッシュ ライン サイズに合わせることで、キャッシュ パフォーマンスを向上させます。たとえば、サイズが 32 バイト未満の構造体を定義する場合、その構造体型のオブジェクトが効率的にキャッシュされるように、それを 32 バイトに揃えることができます。

于 2013-04-15T14:44:32.867 に答える
1

x64 プロジェクトがデフォルトのパッキング アラインメント 16 を使用するのはなぜですか?

x64 では、浮動小数点は SSE ユニットで実行されます。最大の型はアライメント 8 であると述べていますが、それは正しくありません。一部の SSE 組み込み型 ( など__m128) は、アライメントが 16 です。

于 2013-04-15T20:30:57.297 に答える