C# 中的算术异常

发布于 2024-09-09 12:24:05 字数 426 浏览 6 评论 0原文

为什么在 C# 中示例 A 有效、可编译并且只会换行,而示例 B 则无法编译?

A

int val = 0;
val = val + Int32.MaxValue +2;

int val = Int32.MaxValue;
val++;

B

int val = 0;
val = 2147483647 + 1;

int val = 0;
int val = Int32.MaxValue + 1;

我知道默认情况下不会检查算术异常,除非您在配置中使用已检查的方法、块或属性明确执行此操作。我的问题更多地与编译器有关,而不是算术异常如何发生。

Why in C# is Example A valid, compilable and will just wrap while examples B will not compile?

A

int val = 0;
val = val + Int32.MaxValue +2;

or

int val = Int32.MaxValue;
val++;

B

int val = 0;
val = 2147483647 + 1;

or

int val = 0;
int val = Int32.MaxValue + 1;

I know by default that arithmetic exceptions are not checked by default unless you explicitly do so using checked method, block or attribute in the config. My question relates more to compiler then how an arithmetic exception happens.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

贱人配狗天长地久 2024-09-16 12:24:10

它只是与编译时检查的限制有关。有些事情只能在运行时才能知道。

It simply has to do with the limitations of the compile time checking. Certain things can only be known at runtime.

掀纱窥君容 2024-09-16 12:24:09

我知道默认情况下不会检查算术异常,除非您在配置中使用已检查的方法、块或属性明确执行此操作

您不知道,因为该语句不正确。事实上,你知道它是不正确的,因为你提供了一个案例,证明你的陈述是错误的!

我建议您参阅 C# 规范的第 7.6.12 节,为了您的方便,我在此处复制了其中的一部分:

对于没有被任何已检查或未检查的运算符或语句括起来的非常量表达式(在运行时计算的表达式),默认的溢出检查上下文是未检查的,除非外部因素(例如编译器切换和执行环境配置) )要求进行检查评估。

对于常量表达式(可以在编译时完全计算的表达式),始终检查默认的溢出检查上下文。除非将常量表达式显式放置在未经检查的上下文中,否则在表达式的编译时求值期间发生的溢出总是会导致编译时错误。

请参阅规格了解更多详细信息。

I know that arithmetic exceptions are not checked by default unless you explicitly do so using checked method, block or attribute in the config

You do not know that because that statement is incorrect. And in fact you know it to be incorrect because you've provided a case where your statement is proven false!

I refer you to section 7.6.12 of the C# specification, a portion of which I reproduce here for your convenience:

For non-constant expressions (expressions that are evaluated at run-time) that are not enclosed by any checked or unchecked operators or statements, the default overflow checking context is unchecked unless external factors (such as compiler switches and execution environment configuration) call for checked evaluation.

For constant expressions (expressions that can be fully evaluated at compile-time), the default overflow checking context is always checked. Unless a constant expression is explicitly placed in an unchecked context, overflows that occur during the compile-time evaluation of the expression always cause compile-time errors.

See the spec for further details.

葬花如无物 2024-09-16 12:24:08

您的 B 示例在编译时是常量折叠,向编译器表明它肯定会溢出。

由于您的 A 示例使用变量,因此表达式无法(完全)常量折叠,因此编译器无法保证这些值会导致溢出。

例如...

int val = 0;
// some other thread changes `val` to -5...
val = val + Int32.MaxValue +2; // no overflow

但是,如果您知道 val 不会改变,并将 0 分配给 const int

const int startval = 0;
int val = startval + Int32.MaxValue + 2;

您可以获得编译时溢出检查回来,因为该值可以完全确定,因此常量折叠。

Your B examples are constant-folded at compile time, indicating to the compiler that it's guaranteed to overflow.

Because your A examples use variables, the expressions cannot be (completely) constant-folded, so the compiler can't guarantee that the values will result in an overflow.

For instance...

int val = 0;
// some other thread changes `val` to -5...
val = val + Int32.MaxValue +2; // no overflow

However, if you know that val won't change, and assign 0 to a const int:

const int startval = 0;
int val = startval + Int32.MaxValue + 2;

You can get your compile-time overflow check back because the value can be completely determined and therefore constant-folded.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文