使用常量进行算术运算时出现溢出错误

12

我尝试了以下代码:

int x, y;
x = y = int.MaxValue;

int result = x + y;

这段代码运行良好,结果将包含-2(我知道原因)。

但是当进行以下操作:

const int x = int.MaxValue;
const int y = int.MaxValue;

int result = x + y;

这段代码由于溢出问题无法编译通过。为什么?


1
我对这个问题非常感兴趣。 - Josh
1个回答

13

由于xy都是编译时常量,所以x + y也是。编译器“知道”结果会溢出,因此会报错。

您可以通过使用unchecked表达式来修复此问题:

int result = unchecked(x + y);

来自 C# 5 规范第 7.6.12 节 - 在列出 +, -, /* 后:

当上述运算之一产生的结果过大而无法表示为目标类型时,执行操作的上下文控制生成的行为:

  • checked 上下文中,如果操作是常量表达式(§7.19),则会导致编译时错误。
  • unchecked 上下文中,结果将通过丢弃任何不适合目标类型的高位比特来截断。

对于非常量表达式(在运行时评估的表达式)不被任何 checkedunchecked 运算符或语句包围的情况下,默认的溢出检查上下文是 unchecked,除非外部因素(例如编译器开关和执行环境配置)要求进行 checked 评估。

对于常量表达式(可以在编译时完全计算的表达式),默认的溢出检查上下文始终为 checked。除非将常量表达式明确放置在 unchecked 上下文中,否则在表达式的编译时评估过程中发生的溢出总会导致编译时错误。


1
也许有点跑题,但是当用于大型代码体时,unchecked 关键字是否能减少编译时间? - huseyin tugrul buyukisik
@huseyintugrulbuyukisik:如果你能找到一个真实世界的例子,证明这种差异是可以测量的,我会非常惊讶。 - Jon Skeet
Jon问:有人真的“想要”这样做,这合理吗? - John
1
@John:有时候以未经检查的方式表达常量是很有用的,比如对于位模式。不过这种情况相对较少。 - Jon Skeet
1
@John 一个例子是当你需要将 HRESULT 指定为普通的 int(有符号),从十六进制表示中进行转换。它看起来像是 int hr = unchecked((int)0x80070005); - Jeppe Stig Nielsen
显示剩余2条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接