3

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

マシンコードレベルのC++では、postincrement ++演算子はいつ実行されますか?

優先順位のは、postfix ++演算子がレベル2であることを示しています。これは、

int x = 0 ;
int y = x++ + x++ ;  // ans: y=0

接尾辞++は最初に実行されます。

ただし、この行の論理演算は、加算が最初に行われる(0 + 0)ように見えますが、それはどのように行われますか?

私が想像するのは次のとおりです。

// Option 1:
// Perform x++ 2 times.
// Each time you do x++, you change the value of x..
// but you "return" the old value of x there?
int y = 0 + x++ ;  // x becomes 1, 0 is "returned" from x++

// do it for the second one..
int y = 0 + 0 ;  // x becomes 2, 0 is "returned" from x++... but how?
// if this is really what happens, the x was already 1 right now.

したがって、他のオプションは、x++がx+ xよりも優先順位テーブルで高いにもかかわらず、x++によって生成されたコードが加算演算の下に挿入されることです。

// Option 2:  turn this into
int y = x + x ; // 
x++ ;
x++ ;

この2番目のオプションの方が理にかなっているようですが、ここでの操作の順序に興味があります。具体的には、xはいつ変化しますか?

4

4 に答える 4

10

UBである例の詳細にジャンプする代わりに、完全に問題のない次の例について説明します。

int a = 0, b = 0;
int c = a++ + b++;

ここで、演算子の優先順位は、最後の行が次と同等であることを意味します。

int c = (a++) + (b++);

そしてそうではありません:

int c = (a++ + b)++; // compile time error, post increment an rvalue

一方、post増分のセマンティクスは、2つの別個の命令と同等です(これ以降は単なる精神的な図です)。

a++; // similar to: (__tmp = a, ++a, __tmp) 
     // -- ignoring the added sequence points of , here

つまり、元の式はコンパイラによって次のように解釈されます。

auto __tmp1 = a;         // 1
auto __tmp2 = b;         // 2
++a;                     // 3
++b;                     // 4
int c = __tmp1 + __tmp2; // 5

ただし、コンパイラは、次の制約が満たされている限り、5つの命令を並べ替えることができます(x>y平均は、の前、または前xに実行する必要があります)。yxy

1 > 3        // cannot increment a before getting the old value
2 > 4        // cannot increment b before getting the old value
1 > 5, 2 > 5 // the sum cannot happen before both temporaries are created

さまざまな命令の実行順序に他の制約はないため、以下はすべて有効なシーケンスです。

1, 2, 3, 4, 5
1, 2, 5, 3, 4
1, 3, 2, 4, 5
...
于 2011-03-25T15:14:23.687 に答える
7

これ

int y = x++ + x++ ;

未定義の動作です。不合理な結果、プログラムのクラッシュなど、何でも起こり得ます。そんなことはしないでください。

于 2011-03-25T14:35:51.317 に答える
4

C ++には、「シーケンスポイント」と呼ばれるものがあります。シーケンスポイントを介在させずに値を複数回変更した場合、動作は未定義です。

次のことを考慮してください。

int x = 0;
int y = x++ + x++;

yの値は、0、1、またはその他の完全にランダムな値にすることができます。

肝心なのは、それをしないでください。良いものは何もありません。:-)

于 2011-03-25T14:45:03.337 に答える
2

あなたの場合、次のようになります

を使用すると、操作の完了後x++x増分します。

int y = x++ + x++ ;
// First add 0+0
// Increment x
// Increment 

その間

int y = ++x + ++x ;
// Add (increment x) and (increment x) = 1+1 = 2

ただし、コンパイラが異なれば処理も異なり、同じステートメントで2回インクリメントすると、アプリケーションがクラッシュする可能性があります。

于 2011-03-25T14:37:24.833 に答える