9

以下代码段的计算结果为零:

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

然而,如果你这样做:

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

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

那么,这里发生了什么?难道我的理解unchecked错了?

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


编辑: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);

但事实并非如此,第二个给出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(与浮点数相同)
  • decimal.MaxValue + 1 引发 System.OverflowException
于 2011-07-30T14:22:13.837 回答
4

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

在未经检查的上下文中,转换始终成功,并按如下方式进行。

• 该值朝零四舍五入到最接近的整数值。如果这个整数值在目标类型的范围内,那么这个值就是转换的结果。

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

就是这样了。结果未定义。一切都会过去。

于 2011-07-30T15:03:55.483 回答