1

以下の宣言を考えてみましょう。(Visual Studio 2010、警告レベル 4)

#pragma pack(push, 2)
#define PADDING 1 // --- <case 1>
/*
#define PADDING 2 // --- <case 2>
*/
struct foo
{
    char a[PADDING];
    int b;
};

症状

PADDING を<case 1>に設定すると、間違いなく C4121 が生成されます。ただし、 の<case 2>場合、警告なしでコンパイルできます。2 つのケースの構造レイアウトは同じで、"b" のオフセットは 2 バイトです。"b" が境界の倍数に配置されていない
ため、C4121 を期待していました。( MSDNから。2010バージョンは見つかりませんでした。)<case 2>sizeof(int)

質問

<case 1>結果として得られる構造のレイアウト (アライメント) は同じなので、C4121のみを生成することが合理的であるかどうか疑問に思います。
私は何か重要なものを見逃していますか?C4121 を無視する必要がありますか?

PS

実際、私はこのような状況に直面していました

  • デフォルトのアラインメント値 (8 バイト)
  • 未定義 (前方宣言のみ) ク​​ラスのメンバ関数へのポインタ (16 バイト)。

したがって、特定のアライメント値は重要ではないと思います。簡単にするために上記のサンプルコードを書きました。

4

2 に答える 2

1

この警告を無視する場合は、次のことに注意してください。

データがデータのサイズの倍数である境界に配置されていない場合、パフォーマンスが低下する可能性があり、コードを RISC マシンに移植するとコンパイルされません。

少なくとも、リスクを冒して例外をスローできるかどうかを判断する必要があります...

それを解決するために使用#pragma pack()することは良い方法ですが、それには問題があります:

#pragma pack ディレクティブは、構造体のパッキング サイズをプロジェクトの既定のパッキングから減らすためにのみ使用できます。これは、プロジェクト パッキングをこれよりも小さく設定すると、たとえば #pragma pack(8) を使用するライブラリ ヘッダーとの相互運用性の問題につながります。MSDN のドキュメント [5] には、#pragma pack パッキングがプロジェクト パッキング以上の場合、無視されると記載されています。

このため、プロジェクト パッキングをデフォルトの 8 バイト以外の値に設定しないでください。ライブラリ ヘッダーで使用される #pragma pack ディレクティブが破損し、構造間のバイナリ非互換性が発生するためです。

だけでなく :

x86 アーキテクチャは元々、アラインされたメモリ アクセスを必要とせず、それがなくても機能します。

この警告を回避することをお勧めします。より安全になります...

これを解決する方法は、structここで提案されているようにメンバーの順序を逆にすることです: http://msdn.microsoft.com/en-us/library/kabt0ka3%28v=vs.80%29.aspx

EDIT:データ構造のアライメントと は何か、およびそれに伴う問題を説明するもう1つの追加リンク:https : //en.wikipedia.org/wiki/Data_structure_alignment (定義問題のセクションを読むことをお勧めします)

于 2013-07-17T10:15:11.623 に答える
0

コンパイラの問題である可能性があると思います:

#pragma pack(push, 2)
struct foo
{
    char a[3];
    int b;
}; 

int main()
{
    foo f[2];
    cout << "sizeof(f) = " << sizeof(f) << endl;
    cout << "&f[0] =" << &f[0] << endl;
    cout << "&f[1] =" << &f[1] << endl;
    cout << "&f[0].b =" << &(f[0].b) << endl;
    cout << "&f[1].b =" << &(f[1].b) << endl;
}

1 と 3 では警告が表示されますが、2 では表示されませんが、1 と 2 ではアドレスは同じです。

于 2013-07-17T11:17:08.500 に答える