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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/2633661/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-02 05:09:54  来源:igfitidea点击:

How to check for signed integer overflow in C without undefined behaviour?

cinteger-overflow

提问by Ganker

There's (1):

有(1):

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

And (2):

和(2):

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

Whichs is preferred or is there a better way.

这是首选还是有更好的方法。

回答by caf

Integer overflow is the canonical example of "undefined behaviour" in C (noting that operations on unsigned integers never overflow, they are defined to wrap-around instead). This means that once you've executed x + y, if it overflowed, you're already hosed. It's too late to do any checking - your program could have crashed already. Think of it like checking for division by zero - if you wait until after the division has been executed to check, it's already too late.

整数溢出是 C 中“未定义行为”的典型示例(注意对无符号整数的操作永远不会溢出,它们被定义为环绕)。这意味着一旦你执行了x + y,如果它溢出,你已经被冲洗掉了。现在进行任何检查都为时已晚 - 您的程序可能已经崩溃了。把它想象成检查除以零 - 如果你等到除法执行完后再检查,已经太晚了。

So this implies that method (1) is the only correct way to do it. For max, you can use INT_MAXfrom <limits.h>.

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

If xand/or ycan be negative, then things are harder - you need to do the test in such a way that the test itself can't cause overflow.

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

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

回答by Chris Dodd

You can really only check for overflow with unsignedintegers and arithmatic:

你真的只能用unsigned整数和算术检查溢出:

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

The behavior of overflow with signed integers is undefined in C, but on most machines you can use

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

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

This won't work on machines that use any kind of saturating arithmetic

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

回答by clahey

You only have to check one of them. If x + y overflows, it will be less than both x and y. Hence:

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

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

should be sufficient.

应该足够了。

The following site has a bunch of stuff about integer overflow:

以下站点有一堆关于整数溢出的内容:

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

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

If you want to handle negative numbers, it can be expanded:

如果要处理负数,可以展开:

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