【问题标题】:Do the C# and Java specifications spell out the same behavior on signed integer overflow?C# 和 Java 规范是否对有符号整数溢出有相同的规定?
【发布时间】:2016-04-07 08:44:14
【问题描述】:

在 C 和 C++ 中,有符号整数上溢或下溢的行为是未定义的。

在 Java 和 C#(未经检查的上下文)中,行为似乎在一定程度上被定义。


根据 Java 规范,我们有:

整数运算符不以任何方式指示上溢或下溢。

还有:

Java 编程语言使用二进制补码表示整数 [...]


根据 C# 规范,我们有:

[...] 在未经检查的上下文中,溢出被忽略,任何不适合目标类型的高位被丢弃。


通过测试两者,我得到了预期的环绕结果。从规范的措辞来看,我觉得在 Java 中结果是可移植的(因为该语言需要 2 的补码表示),而 C# 可能有也可能没有这个结果(因为它似乎没有指定表示 -只是高阶位被丢弃)。

那么,两种语言规范是否保证在所有平台上的行为相同(只是措辞不同)?还是在我的测试用例(在 x86 和 Sun 的 JRE 和 Microsoft 的 .NET 下)它们只是碰巧彼此相同,但理论上在其他架构或实现上可能不同?

【问题讨论】:

  • 如果行为是为语言明确定义的,为什么平台之间应该不同?!
  • @HannoBinder 当我使用术语 well-defined 时,我的意思是它与 undefined 形成对比——在 Java 和 C# 中都不是未定义的.但我仍然不明白规范是否说明了可移植结果或只是将行为保留为实现定义
  • 如果您查看System.Int32 documentation 中的Working with Non-Decimal 32-Bit Integer Values,您可以看到,至少对于整数而言,表示形式是相同的所有平台。我怀疑其他类型也一样。
  • 即使使用 2 的补码,您也可以强制饱和(而不是环绕),并返回最高整数,正好在 2 的补码中。所以我不明白为什么这会推断出可移植性。

标签: java c# language-lawyer integer-overflow code-conversion


【解决方案1】:

在 Java 中,可移植性由 Java Language Specification 确保,它说明了基本类型 int 被签名的 32 位 2 的补码整数的所有规则。然后标准库本身实现了Integer类,它包装了int值并添加了一些便利方法,但就范围和溢出而言基本相同。

在 .NET 中,CLR 也定义了一些原始类型,这些类型也由不同的类和别名包装,具体取决于语言。见Common Language Specification - esp. Common Type Systtem

所以要回答您的问题,在 Java 中,代码是可移植的,由语言规范和 JVM 实现确保。在 .NET 中(因为 CLR 也运行 C++ 代码,而 C++ 代码又可能不符合 CLS 的操作更接近铁级别),您必须通过将其设置为 CLS Compliant 来确保您的代码是可移植的。好消息是,使用 int 和/或 System.Int32 可以让您符合 CLS,便于携带。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-03-15
    • 2019-08-23
    • 2017-05-13
    • 2017-06-19
    • 1970-01-01
    • 2018-09-07
    • 1970-01-01
    相关资源
    最近更新 更多