Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/273.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# unchecked()导致的奇怪结果,可能是编译器错误?_C#_Casting_Unchecked - Fatal编程技术网

C# unchecked()导致的奇怪结果,可能是编译器错误?

C# unchecked()导致的奇怪结果,可能是编译器错误?,c#,casting,unchecked,C#,Casting,Unchecked,以下代码段的计算结果为零: int result = unchecked((int)double.MaxValue); 鉴于,如果您这样做: double x = double.MaxValue int result = (int)x; 结果是(你会猜到吗?int.MinValue)。这一事实本身就够奇怪了(见下文),但我的印象是,未选中是为了迫使编译器发出假装不知道转换肯定会失败和/或发生溢出的代码。换句话说,它应该给出与编译器不知道所涉及的值时相同的结果(假设它是在禁用“检查算术溢出”的

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

int result = unchecked((int)double.MaxValue);
鉴于,如果您这样做:

double x = double.MaxValue
int result = (int)x;
结果是(你会猜到吗?
int.MinValue
)。这一事实本身就够奇怪了(见下文),但我的印象是,
未选中
是为了迫使编译器发出假装不知道转换肯定会失败和/或发生溢出的代码。换句话说,它应该给出与编译器不知道所涉及的值时相同的结果(假设它是在禁用“检查算术溢出”的情况下编译的)

那么,这是怎么回事?我对未选中的
的理解是否错误

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


编辑:
int.MinValue
非常容易解释:
cvttsd2si
在溢出但异常被屏蔽时给出0x8000000。这是JIT编译器使用的指令,可以在反汇编窗口中看到。但这并不能解决问题的任何部分


根据ECMA 334(C#2规范),未选中的
关键字应始终截断,因此在这两种情况下,结果均应为零:

int result1 = unchecked((int)double.MaxValue);
double x = double.MaxValue;
int result2 = unchecked((int)x);
但事实并非如此,第二个函数给出了
int.MinValue
。这对我来说仍然像是编译器的bug。

来自

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

默认上下文已选中

在选中的上下文中,如果表达式生成的值 在目标类型的范围之外,结果取决于 表达式是常量还是非常量。常数 表达式会导致编译时错误,而非常量表达式 在运行时进行计算并引发异常

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

    • 太好了,我找到了。在规范的深处,有以下几个方面:

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

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

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


      就这样。结果未定义。一切正常。

      我要冒昧猜测一下,这与double和int类型的二进制表示有关。@Jon Grant:我怀疑,0x8000000是-0作为float(而不是double的正确大小)。但是,cvttsd2si指定0x8000000是双精度太大且溢出异常被屏蔽时的结果。这就是
      int.MinValue
      的来源,但是零呢?记住这一点,当你认为它是一个编译器错误时,它不是-它是你的代码或理解。FYIYou没有查看实际代码,这些表达式是由抖动计算的。工具+选项,调试,常规,取消勾选“抑制JIT优化”选项。抖动不会发出任何代码来试图规范溢出行为,这太昂贵了。@Hans Passant:我在发布模式下抛出了一个异常,并在抛出Yes时附加了调试器,但这并不能真正解释发生了什么,是吗?事实上,甚至有一个与未选中((int)double.MaxValue)
和未选中((int)MaxValueOfDouble)
不同的答案,其中
MaxValueOfDouble
是一个设置为
double.MaxValue
@harold:double.MaxValue大于int所能容纳的值。是的,很明显,我对结果是int.MinValue或零没有任何问题,让我感到不安的是,根据不同的情况,结果会有所不同。@harold:如果要使用未选中的关键字,“结果被截断”-可能是0。如果未选中,它应该告诉您它超出了int的范围。因此我可以从中得出结论,对于常量表达式和变量表达式,未选中的关键字的行为不同。我找不到的地方说这应该是行为。