【问题标题】:Why x - y does not overflow for TMin in this function? Why is the function wrong in this case?为什么 x - y 在此函数中不会溢出 TMin?为什么在这种情况下功能错误?
【发布时间】:2014-11-15 19:52:24
【问题描述】:

我正在阅读有关此功能的信息:

int tadd_ok ( int x, int y ) {  
    int sum = x + y;  
    int negative_overflow = x < 0 && y < 0 && sum >= 0;   
    int positive_overflow = x >=0 && y >= 0 && sum < 0;  
    return !negative_overflow && !positive_overflow;
}  

当我们将 TMin(即最小的 2 的补码)作为 y 的参数传递时,此函数存在问题。
在这种情况下,传入时 -y 将是 -y,即仍然是 TMin 第一个条件将显示我们对于 x 的值为负数的值为负溢出。
然后我读到实际上在这些情况下“x - y 不会溢出”。

我的理解是这个函数的问题是它没有考虑传递最小负数的极端情况。我可以看到它会返回一个negative_overflow 我看不到/不明白为什么这是错误的。
谁能帮我理解这个?

【问题讨论】:

  • 这个函数的问题是它试图检测可能发生的溢出之后。这是错误的,因为已经发生了溢出的鼻守护进程。
  • @ouah:我猜正确的函数会在它发生之前尝试检测?我不知道这些方法有什么区别。除了这个错误的方法之外,为什么TMin被认为不会溢出?
  • 问题在于,正如 ouah 所说,C 编译器试图把你搞砸而不是帮助你。许多 C 编译器不会使用 2s 补码算法让有符号整数溢出,然后让您检查结果和,而是假定 oevrflow 永远无法帮助优化溢出检查。有关详细信息,请参阅this question
  • @Cratylus -INT_MIN 不会换行,它会调用未定义的行为。有符号整数溢出调用未定义的行为。
  • 是的,这是特定于 C 的,而且很麻烦。 C 标准来自并非每台计算机都使用 2s 补码算法的时代,因此有符号溢出被认为是未定义的行为。不幸的是,这并不意味着“未指定的行为”。当有符号溢出发生时,许多编译器会做一些无意义的事情,而不是总是以相同的方式溢出。

标签: c types integer integer-overflow integer-arithmetic


【解决方案1】:

您不能在事后检查有符号整数溢出,您必须在执行操作之前检查。这是因为算术运算中的有符号整数溢出在 C 和 C++ 中是 undefined behavior。一旦调用了未定义的行为,程序的结果就会变得不可预测(see my comment above for one of the most unexpected results I have seen)。对于 C,我们可以通过转到 draft C99 standard 部分 6.5 Expressions 看到这一点:

如果在评估过程中出现异常情况 表达式(也就是说,如果结果不是数学定义的,或者 不在其类型的可表示值范围内),行为 未定义。

Cert 提供了关于如何防止签名溢出的可靠指南:INT32-C. Ensure that operations on signed integers do not result in overflow,对于补充,该文档建议使用以下方法:

#include <limits.h>

void f(signed int si_a, signed int si_b) {
  signed int sum;
  if (((si_b > 0) && (si_a > (INT_MAX - si_b))) ||
      ((si_b < 0) && (si_a < (INT_MIN - si_b)))) {
    /* Handle error */
  } else {
    sum = si_a + si_b;
  }
  /* ... */
}   

该文档涵盖了所有可能的溢出操作,并为每种情况提供了建议。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-07-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多