【发布时间】:2015-08-02 18:14:39
【问题描述】:
表达式 int.Minvalue / -1 导致根据 C# 规范实现定义的行为:
7.8.2 除法运算符
如果左操作数是可表示的最小 int 或 long 值,而右操作数是 –1,则 发生溢出。在检查的上下文中,这会导致 要抛出的 System.ArithmeticException(或其子类)。在一个 未经检查的上下文,它是 实现定义 是否 System.ArithmeticException(或其子类)被抛出或 溢出未报告,结果值为 左操作数。
测试程序:
var x = int.MinValue;
var y = -1;
Console.WriteLine(unchecked(x / y));
这会在 .NET 4.5 32 位上引发 OverflowException,但不是必须的。
为什么规范将结果实现定义为?以下是反对这样做的理由:
- 在这种情况下,x86
idiv指令总是会导致异常。 - 在其他平台上,可能需要运行时检查来模拟这一点。但是,与部门的成本相比,该支票的成本会很低。整数除法非常昂贵(15-30 个周期)。
- 这会带来兼容性风险(“一次写入就无法运行”)。
- 开发者惊喜。
同样有趣的是,如果x / y 是编译时常量,我们确实会得到unchecked(int.MinValue / -1) == int.MinValue:
Console.WriteLine(unchecked(int.MinValue / -1)); //-2147483648
这意味着x / y 可以具有不同的行为,具体取决于所使用的句法形式(不仅取决于x 和y 的值)。这是规范允许的,但这似乎是一个不明智的选择。为什么 C# 是这样设计的?
similar question 指出了规范中规定了这种确切行为的位置,但它没有(充分)回答为什么语言是这样设计的。没有讨论替代选择。
【问题讨论】:
-
dimitry 在this answer 上的评论表明规范并不总是这样读。
-
@HenkHolterman 这个问题是关于语言设计的。建议的副本没有回答这个问题。 (重新打开我自己的问题有点尴尬。)
-
why 部分在骗子的答案中得到了充分的回答。当您认为您有更具体的问题时,您应该链接到原始问题并说明差异。
-
@HenkHolterman 现在会这样做。
-
@HenkHolterman 是的,他解释了我所知道的 x86 情况。但是为什么要定义这个实现呢?我不反对抛出异常。我想知道为什么甚至允许替代行为。
标签: c# language-design