2

重複の可能性:
未定義の動作とシーケンス ポイント

次のマクロを理解できません。

#define CUBE(x) ((x)*(x)*(x))

私のコード:

int y=5;
print("Cube = %d",CUBE(++y));

このコードは 512 を出力します (Microsoft Visual Studio を使用)

私はこれが印刷されることを期待していました: ((++5)*(++6)*(++7)) = (6*7*8) = 336.
これはどのように評価されますか?

また、同じコードが Dev C++ コンパイラを使用してコンパイルされ、結果は 392 です!!!

まったく同じコードに対して 2 つのコンパイラが異なる結果を示す理由を誰か説明できますか?

これはどのように++y評価されますか?

4

5 に答える 5

3

マクロが展開されると、yシーケンス ポイントが介在することなく、 の値が複数回変更されます。
これは未定義の動作です。

未定義の動作とは、任意の動作が可能であることを意味します。あなたのプログラムは有効な C プログラムではありません。
したがって、異なるコンパイラでは異なる出力が表示されます。

于 2012-06-08T17:23:25.717 に答える
1

CUBE(++y)); は (++y * ++y * ++y) になります - それはどのような順序で評価されますか?

技術的に言えば、関数ポイント間で同じ変数を変更することは未定義です

編集:未定義の動作とシーケンス ポイントを参照してください

Visual C++ はこれをy+=3; y*y*y; so 8*8*8 = 512
382 is 7*7*8 と評価しているように見えるので、Dev C++ はおそらく最初の部分を次のように評価しますy+=2; y*y;49*y++

于 2012-06-08T17:21:58.250 に答える
1

式にはシーケンス ポイントがないため、副作用 (つまり、インクリメントの結果y) が表示される時間は未定義です。簡単に言えば、コンパイラは、式の評価が完了する前に、いつでも自由に結果を に格納++yできyます。

これは、副作用のある式を取るマクロを作成する危険性です。同等の機能を使用した方がはるかに優れています。

于 2012-06-08T17:22:46.697 に答える
0

We need to see the ASM (assemble) of the code (gcc -S .c) to know what exactly it is happening.

In Dev C++ Compiler ASM looks like

1)        movl    $5, 28(%esp)
2)        addl    $1, 28(%esp)
3)        addl    $1, 28(%esp)
4)        movl    28(%esp), %eax
5)        imull   28(%esp), %eax
6)        addl    $1, 28(%esp)
7)        imull   28(%esp), %eax

It shows the value 5 was moved to %esp (1) and then added two time there (2 & 3), so now the value of y becomes 7; This value is now moved to eax register (4) and got multiplied 7 * 7 (5); Now add 1 to value y (6) and then multiply with eax; so the answer is 7 * 7 * 8 = 392

In Microsoft visual studio it will be of 8 * 8 * 8.

于 2012-06-08T17:58:04.260 に答える
0

プリコンパイラはこのマクロを評価します

#define CUBE(x) ((x)*(x)*(x))

あなたのコードで:

int y=5;
print("Cube = %d",CUBE(++y));

int y=5;
print("Cube = %d",((++y)*(++y)*(++y)));

このようなコードの記述は混乱を招き、結果は未定義です。

コンパイラが異なれば、動作も異なる場合があります。

このような構造を使用しないようにすると、そのような問題に直面することはありません。

于 2012-06-08T17:24:43.267 に答える