9

次のスニペットはゼロと評価されます。

int result = unchecked((int)double.MaxValue);

一方、これを行う場合:

double x = double.MaxValue
int result = (int)x;

結果は(これを推測しますか?)int.MinValueです。その事実だけでも十分に奇妙です[以下を参照]がunchecked、変換が確実に失敗したり、オーバーフローが発生したりすることを知らないふりをするコードをコンパイラーに強制的に発行させることを意図した印象を受けました。つまり、コンパイラが関連する値を認識していない場合と同じ結果が得られるはずです(「算術オーバーフローのチェック」が無効になっている場合)。

それで、ここで何が起こっているのですか?私の理解はunchecked間違っていますか?

C#/。NET標準に従って、結果の1つは「間違っている」ですか?


編集:int.MinValue簡単に説明できます:cvttsd2siオーバーフローが発生したが例外がマスクされている場合に0x80000000を返します。これは、逆アセンブリウィンドウに表示されるように、JITコンパイラによって使用される命令です。しかし、それは問題のどの部分も解決しません。


ECMA 334(C#2仕様)によると、uncheckedキーワードは常に切り捨てられる必要があるため、次の両方の場合で結果はゼロになります。

int result1 = unchecked((int)double.MaxValue);
double x = double.MaxValue;
int result2 = unchecked((int)x);

しかし、そうではありません、2番目のものはを与えint.MinValueます。これはまだ私にはコンパイラのバグのようなにおいがします。

4

2 に答える 2

4

未チェックのキーワードに関するMSDNから、

チェックされていないコンテキストで、式が宛先タイプの範囲外の値を生成する場合、結果は切り捨てられます。

デフォルトのコンテキストがチェックされ、

チェックされたコンテキストで、式が宛先タイプの範囲外の値を生成する場合、結果は式が定数であるか非定数であるかによって異なります。定数式はコンパイル時エラーを引き起こしますが、非定数式は実行時に評価され、例外が発生します。

最後に、Double/Floatはラップしません。

  • int.MaxValue + 1 == int.MinValue(オーバーフローして例外なくラップアラウンドします)
  • uint.MaxValue + 1 == 0(符号なしであるため、ゼロにオーバーフローします。例外はスローされません)
  • float.MaxValue + 1 == float.MaxValue(はい、ランタイムはオーバーフローを処理し、例外はスローされませんが、intとuintの動作は異なります)
  • double.MaxValue + 1 == double.MaxValue(floatと同じ)
  • decimal.MaxValue+1はSystem.OverflowExceptionをスローします
于 2011-07-30T14:22:13.837 に答える
4

素晴らしい、私はそれを見つけました。仕様の奥深くに埋め込まれているのは、次のとおりです。

チェックされていないコンテキストでは、変換は常に成功し、次のように進行します。

•値は、ゼロに向かって最も近い整数値に丸められます。この整数値が宛先タイプの範囲内にある場合、この値は変換の結果です。

それ以外の場合、変換の結果は宛先タイプの不特定の値になります。

以上です。結果は未定義です。すべてが行きます。

于 2011-07-30T15:03:55.483 に答える