The following snippet evaluates to zero:
int result = unchecked((int)double.MaxValue);
Whereas, if you do this:
double x = double.MaxValue
int result = (int)x;
The result is (would you even guess this?) int.MinValue
. That fact alone is weird enough[see below], but I was under the impression that unchecked
was meant to force the compiler into emitting code that pretends not to know that a conversion will definitely fail and/or some overflow happens. In other words, it should give the same result as when the compiler has no knowledge of the values involved (assuming it is compiled with "Check for arithmetic overflow" disabled)
So, what's going on here? Is my understanding of unchecked
wrong?
Is one of the results "wrong", as per the C#/.NET standard?
edit: the int.MinValue
is explained easily enough: cvttsd2si
gives 0x80000000 when there would have been overflow but the exception is masked. That's the instruction used by the JIT compiler, as can be seen in the disassembly window. That doesn't solve any part of the issue though.
According to ECMA 334 (C# 2 spec), the unchecked
keyword should always truncate and therefore the result should be zero in both of these cases:
int result1 = unchecked((int)double.MaxValue);
double x = double.MaxValue;
int result2 = unchecked((int)x);
But it isn't, the second one gives int.MinValue
. This still smells like compiler bug to me.
See Question&Answers more detail:
os 与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…