有(1):
// assume x,y are non-negative
if(x > max - y) error;
还有第二个条件:
// assume x,y are non-negative
int sum = x + y;
if(sum < x || sum < y) error;
哪种方法更好或是否有更好的方法。
有(1):
// assume x,y are non-negative
if(x > max - y) error;
还有第二个条件:
// assume x,y are non-negative
int sum = x + y;
if(sum < x || sum < y) error;
哪种方法更好或是否有更好的方法。
在C语言中,整数溢出是“未定义行为”的典型例子(需要注意的是,无符号整数运算永远不会溢出,它们被定义为环绕)。这意味着一旦执行了x+y
,如果发生了溢出,则已经无法进行任何检查——你的程序可能已经崩溃。就像检查除以零一样——如果等到除法执行后再检查,那就为时已晚。
因此,这意味着方法(1)是唯一正确的方法。对于max
,您可以使用来自<limits.h>
的INT_MAX
。
如果x
和/或y
可能为负数,则事情就变得更加困难——您需要以不会导致溢出的方式进行测试。
if ((y > 0 && x > INT_MAX - y) ||
(y < 0 && x < INT_MIN - y))
{
/* Oh no, overflow */
}
else
{
sum = x + y;
}
您只能使用无符号整数和算术运算来检查溢出:
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 */
}
这可能需要编译时标志来让编译器强制执行换行语义,并且在使用任何饱和或陷阱算术的机器上无法工作。
-fwrapv
)来启用有符号环绕作为一种语言扩展。这不仅是跨架构的可移植性问题。 - strcat你只需要检查其中一个。如果 x + y 溢出,它将小于 x 和 y。因此:
int sum = x + y;
if (sum < x) error;
应该足够了。
以下网站有关于整数溢出的大量内容:
如果你想处理负数,可以进行扩展:
int sum = x + y;
if (y >= 0) {
if (sum < x) error;
} else {
if (sum > x) error;
}
x+y
溢出,程序就具有未定义行为。在执行溢出操作之前,你必须进行检查-就像你对整数除以零一样。 - caf
sum < x
和sum < y
。 - Paweł Bylicaunsigned
的,其中包装是定义良好的行为。对于有符号的int
来说更难,因为你不能只是先加上去,然后再检查是否溢出,那已经是未定义行为了,因此编译器可以假设没有溢出! - Peter Cordes