0

テストコードは次のとおりです。

#include <stdio.h>

struct test
{
   int m[1];
};

struct test2: public test
{
   int m1[22];
   void set(int x, int y) { m[x] = y; }
};

int main()
{
    test2 t;
    t.m[1] = 123;
    t.set(0, 0);
    t.set(1, 1);
    printf("%d %d\n", t.m[0], t.m[1]);
    return 0;
}

最適化なしで 1 回、最適化ありで 1 回コンパイルします。

$ g++ -O0 testf.cpp 
$ ./a.out 
0 1
$ g++ -O2 testf.cpp 
$ ./a.out 
1 123

gcc は配列サイズ m[1] を認識し、常に最初の要素 m[0] にアクセスするように最適化しているように思えます。問題は、それは最適化のバグなのか、それとも一部の C++ ルールが壊れているため、gcc が何をするのかということです。もしそうなら、どのルールですか?

m1[22] メモリが余分にあるため、メモリ/スタック オーバーランは発生しないことに注意してください (これは実際のアプリの設計によるものです)。それが良いプログラミング スタイルかどうかは尋ねません。上記の質問に対する正しい答えを知りたいだけです。

更新: std の詳細で回答を受け入れましたが、最大の助けは次のリンクのコメントでした: 「構造ハック」は技術的に未定義の動作ですか?

4

2 に答える 2

12

あなたのプログラムには未定義の動作があります。ここ:

t.m[1] = 123;

範囲外の場所に書き込みを行っています (mは 1 つの要素の配列であり、存在しない 2 番目の要素にインデックスを付けています)。同じことが次の場合にも当てはまります。

t.set(1, 1);

それは基本的にやってしまうので:

m[1] = 1;

未定義の動作、特に一貫性のない動作を持つプログラムからは何も期待できません。

于 2013-05-03T18:13:22.187 に答える