2

重複の可能性:
未定義、未指定、および実装定義の動作
未定義の動作とシーケンス ポイント
C、C++、Java、および C# におけるインクリメント演算子の前後の動作

私はこのコードスニペットを持っています:

int x = 2;
int y = x + 4 * ++x;
// what is y???

そして、c/c++でコンパイルしてテストすると、次のようになります。

// C/C++
y is 15

しかし、C#経由で取得します

// C#
y is 14

なぜ?


ILの一部は次のとおりです。

locals init ([0] int32 x,
[1] int32 y)
IL_0000: nop
IL_0001: ldc.i4.2
IL_0002: stloc.0
IL_0003: ldloc.0
IL_0004: ldc.i4.4
IL_0005: ldloc.0
IL_0006: ldc.i4.1
IL_0007: add
IL_0008: dup
IL_0009: stloc.0
IL_000a: mul
IL_000b: add
IL_000c: stloc.1
IL_000d: ldloca.s y
4

2 に答える 2

5
int y = x + 4 * ++x;

CおよびC++では、各オペランドの評価の順序は指定されていません。つまり、どちらかxまたは4*++x他のオペランドの前に評価できます。オペランドの評価順序が指定されていないため、式全体の結果は指定されていません。

xが前に評価された場合4*++x、次のyように計算されます。

int y = x + 4 * ++x; //original

int y = 2 + 4 * ++x  //evaluate x first
      = 2 + (4 * 3)  //evaluate 4 *++x then
      = 14;

同様に、がの4*++x前に評価された場合x

int y = x + 4 * ++x; //original

int y = x + (4*3)  //evaluate 4 * ++x first
      = 3 + 12   //evaluate x then  (x is incremented)
      = 15;

C#では、オペランドを左から右に評価する必要があるため、常に最初の動作が得られ、結果として14が得られます。

于 2011-10-23T10:52:24.357 に答える
2

実際、C ++では、式の評価順序が常に指定されているとは限らないため、未定義の動作が発生します。したがって、xを最初に使用したときに古い値と新しい値のどちらを読み取るかは不明です。両方とも可能であり、実際には、何が起こるかは未定義であると標準が明示的に述べているため、何でも可能です。

安全な言語としてのC#は、このような状況を許容できないため、評価の順序をより厳密に定義します。

于 2011-10-23T10:53:42.183 に答える