【问题标题】:Why may an overflow occur in the following program?为什么下面的程序会发生溢出?
【发布时间】:2017-08-12 17:21:05
【问题描述】:
void main () {
  int i;
  if (i < 0) { i = -i; };
}

谁能帮我理解为什么上面的程序会发生溢出?

【问题讨论】:

  • 未定义的行为。变量未初始化。取反可能的最大负整数在二进制补码算术中产生相同的值
  • 在 2 的补码中,| INT_MIN | > INT_MAX
  • i == INT_MIN 用二进制补码表示时。

标签: c integer integer-overflow


【解决方案1】:

可能会发生溢出,因为二进制补码中整数表示的范围不是对称的:可以表示的最小负数的大小是可以表示的最大正数的大小加一。例如,在 32 位系统上,值为 -2,147,483,6482,147,483,647。这就是为什么否定-2,147,483,648 会导致溢出:否定的结果,一个正值2,147,483,648,不能用相同大小的int 表示。

请注意,这个问题的反面是不成立的:否定一个正数不会导致溢出:

if (i > 0) { i = -i; } // No overflow here

【讨论】:

  • @Tom 请注意,MSVC 在limits.h 中有#define INT_MIN (-2147483647 - 1)
【解决方案2】:

您在堆栈中的“i”值在 main 启动时未定义。在调用 main() 之前运行的启动代码可以在那里留下任何东西。

除了Kashif 所说的,负整数可以比非负整数低一个值,因为负数不需要为零留出空间。符号位中的“1”,所有剩余位为零,当符号反转时会导致溢出。

在 16 位中:-0x8000 == ~0x8000 + 1 == 0x7FFF + 1 == 0x8000
// "-" 负值 == 反转 + 1 == 反转 + 1 == 最终相同

此值的可能值很低,但存在。除非堆栈恰好包含有问题的数字,否则它不会发生。

【讨论】:

    【解决方案3】:

    整数溢出的原因是算术运算尝试创建的数值超出了可以用给定位数表示的范围,或者大于最大值或小于最小可表示值。

    • 好吧,在你的情况下,变量i 没有被初始化。所以这里会发生的是分配给整数类型变量i的内存空间将包含一些垃圾值。
    • 如果内存地址包含可能的最大整数值-2^31(-2,147,483,648),则取反该值将导致整数溢出。

    我希望这会有所帮助。

    【讨论】:

      猜你喜欢
      • 2017-09-04
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2023-03-16
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多