【问题标题】:Why is integer overflow undefined behavior only for signed integers, and not for unsigned integers?为什么整数溢出未定义行为仅适用于有符号整数,而不适用于无符号整数?
【发布时间】:2021-01-31 18:47:08
【问题描述】:

使有符号整数溢出未定义行为的目的是允许编译器优化。但是,这难道不是一个同样有效的论点,也可以使无符号整数溢出未定义行为吗?

【问题讨论】:

  • 有符号整数有不同的表示形式,溢出行为也不同。据我所知,只有一种表示用于无符号匹配。
  • 请注意,在 C++ 术语中,无符号整数永远不会溢出:它们只能环绕,因为标准要求对无符号整数使用模运算整数。
  • “为什么语言设计者做出这个决定而不是那个决定”类型的问题通常是无法回答的。

标签: c++


【解决方案1】:

保持有符号整数溢出未定义的目的可能是编译器优化1。但是原始的原因是标准没有定义有符号整数的位表示。不同的实现提供了不同的有符号整数表示,它们的溢出特性也会不同。这只是允许的,因为标准没有定义这些溢出特性是什么。

相比之下,无符号整数位表示总是明确定义的(否则,您无法有效地执行大量按位运算),因此它们的溢出行为也可以明确定义。

特定大小的无符号整数的布尔运算,在该值表示下,以最大无符号值 + 1 为模。因此,标准有一种方法可以说明任何数学运算的结果:它是预期的数字结果取模最大无符号值 + 1。

也就是说,如果你有一个 16 位的无符号整数,它持有 65535,然后你给它加 1,则数值结果是 65536。但是,你得到一个 16 位数字的结果是 0。这就是标准对其进行了定义,因为这是布尔算术对特定位深度的工作方式。表示定义了行为。

相比之下,不同的有符号整数形式具有不同的溢出特性。如果标准在 16 位有符号整数中定义了 32767 + 1 的特定含义,那么如果特定的有符号整数表示不能自然地提供该答案,则编译器将不得不更改将这些值添加到 produce那个答案。对于有符号/幅度,此加法结果为 -0。如果标准使实际行为成为现实,那么每二进制补码实现将无法仅添加数字。它必须检查溢出并捏造结果。

在每个数学运算上。

1 还有其他原因,例如大多数代码不能容忍它被定义得那么好。这是大多数有符号整数溢出的代码,如果定义明确的话,也会被破坏

【讨论】:

  • 我不确定我是否遵循这个。有符号整数表示是实现定义的;不允许编译器对这些位发生的事情含糊其辞。那么为什么不遵循溢出行为呢?
  • @Sneftel 示例:一些硬件使用(使用)有符号幅度;一些使用 1s 补码,其他硬件可能会在签名溢出等时捕获(故障)
  • @RichardCritten 是的,我意识到这一点。因此我的评论。
  • @Sneftel:表示是实现定义的,它们的含义不是。要定义整数溢出,必须声明当您取最大有符号整数并将其加 1 时获得的数字。定义它需要定义一个表示或强制所有表示做任何需要符合特定答案的事情。
猜你喜欢
  • 1970-01-01
  • 2017-05-13
  • 1970-01-01
  • 1970-01-01
  • 2022-01-20
  • 2012-11-16
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多