unchecked() 的奇怪结果,可能是编译器错误吗?
以下代码段的计算结果为零:
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
。对我来说,这仍然像是编译器错误。
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.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
来自 MSDN 上未经检查的关键字,
检查默认上下文,
最后,Double/Float 不换行。
From MSDN on unchecked keyword,
The default context is checked,
Finally, Double/Float does not wrap.
太好了,我找到了。在规范的深处,有以下内容:
就是这样。结果是未定义的。一切顺利。
Great, I found it. Buried deep inside the spec, there is a the following:
So that's it. The result is undefined. Everything goes.