来自unchecked()的奇怪结果,可能的编译器错误?

时间:2011-07-30 14:03:07

标签: c# casting unchecked

以下代码段评估为零:

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

然而,如果你这样做:

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

结果是(你会猜到这个吗?)int.MinValue。仅这个事实就足够了[见下文],但我的印象是unchecked意味着强制编译器发出代码,假装不知道转换肯定会失败和/或发生某些溢出。换句话说,它应该给出与编译器不知道所涉及的值时相同的结果(假设编译时禁用了“检查算术溢出”)

那么,这里发生了什么?我对unchecked的理解是错误的吗?

根据C#/。NET标准,其中一个结果是“错误的”吗?


编辑:int.MinValue很容易解释:当cvttsd2si溢出但异常被屏蔽时,unchecked给出0x80000000。这是JIT编译器使用的指令,如反汇编窗口中所示。但这并没有解决问题的任何部分。


根据ECMA 334(C#2规范),int result1 = unchecked((int)double.MaxValue); double x = double.MaxValue; int result2 = unchecked((int)x); 关键字应始终截断,因此在这两种情况下结果应为零:

int.MinValue

但事实并非如此,第二个给出了{{1}}。这对我来说仍然像编译错误。

2 个答案:

答案 0 :(得分:4)

来自MSDN on unchecked keyword

  

在未选中的上下文中,如果表达式生成的值为   在目标类型范围之外,结果将被截断。

选中默认上下文

  

在已检查的上下文中,如果表达式生成的值为   在目的地类型范围之外,结果取决于   表达式是常数还是非常数。不变   表达式导致编译时错误,而非常量表达式   在运行时进行评估并引发异常。

最后,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

答案 1 :(得分:3)

太好了,我找到了。深埋在规范中,有以下内容:

  

在未经检查的上下文中,转换始终成功,并按以下步骤继续。

     

•该值向零舍入为最接近的整数值。如果此整数值在目标类型的范围内,则此值是转换的结果。

     

否则,转化结果是目的地类型的未指定值。

就是这样。结果未定义。一切都好。