如何在没有未定义行为的情况下检查C中的有符号整数溢出?

时间:2010-04-13 22:31:59

标签: c integer-overflow

有(1):

// assume x,y are non-negative
if(x > max - y) error;

和(2):

// assume x,y are non-negative
int sum = x + y;
if(sum < x || sum < y) error;

哪个是首选或有更好的方法。

3 个答案:

答案 0 :(得分:58)

整数溢出是C中“未定义行为”的规范示例(注意无符号整数上的操作永远不会溢出,而是定义为环绕转换)。这意味着一旦你执行了x + y,如果它已经溢出,你就已经被强行了。做任何检查都为时已晚 - 您的程序可能已经崩溃了。可以把它想象为检查除零 - 如果你等到除法执行后再检查,那已经太晚了。

所以这意味着方法(1)是唯一正确的方法。对于max,您可以使用INT_MAX中的<limits.h>

如果x和/或y可能是否定的,那么事情就更难了 - 您需要以测试本身不会导致溢出的方式进行测试。

if ((y > 0 && x > INT_MAX - y) ||
    (y < 0 && x < INT_MIN - y))
{
    /* Oh no, overflow */
}
else
{
    sum = x + y;
}

答案 1 :(得分:6)

您实际上只能通过unsigned整数和算术检查溢出:

unsigned a,b,c;
a = b + c;
if (a < b) {
    /* overflow */
}

在C中未定义带有符号整数的溢出行为,但在大多数机器上都可以使用

int a,b,c;
a = b + c;
if (c < 0 ? a > b : a < b) {
    /* overflow */
}

这不适用于使用任何类型的饱和算法的机器

答案 2 :(得分:-5)

您只需要检查其中一个。如果x + y溢出,它将小于x和y。因此:

int sum = x + y;
if (sum < x) error;

应该足够了。

以下网站有很多关于整数溢出的内容:

http://www.fefe.de/intof.html

如果您想处理负数,可以进行扩展:

int sum = x + y;
if (y >= 0) {
   if (sum < x) error;
} else {
   if (sum > x) error;
}