测试两个整数之和是否可能溢出

时间:2011-08-07 04:51:55

标签: c

来自C陷阱和陷阱

  

如果a和b是两个整数变量,则称为非负数   测试a+b是否可能溢出使用:

     if ((int) ((unsigned) a + (unsigned) b) < 0 )
        complain();

我没有得到如何将两个整数的总和与零进行比较会让你知道有溢出?

7 个答案:

答案 0 :(得分:17)

您看到的用于测试溢出的代码只是假的。

对于有符号整数,您必须按以下方式进行测试:

if (a^b < 0) overflow=0; /* opposite signs can't overflow */
else if (a>0) overflow=(b>INT_MAX-a);
else overflow=(b<INT_MIN-a);

请注意,如果两个数字中的一个是常数,则可以简化案例。

对于无符号整数,您可以像这样测试:

overflow = (a+b<a);

这是可能的,因为无符号算术被定义为包装,这与在溢出时调用未定义行为的有符号算法不同。

答案 1 :(得分:2)

当发生溢出时,总和超出某个范围(让我们说这个):

-4,294,967,295 < sum < 4,294,967,295

因此当总和溢出时,它会回绕并返回到开头:

4,294,967,295 + 1 = -4,294,967,295

如果总和为负且你知道这两个数字是正数,则总和溢出。

答案 2 :(得分:2)

如果a和b已知为非负整数,则序列(int)((无符号)a +(无符号)b)在溢出时确实会返回负数。

假设4位(最大正整数为7且最大无符号整数为15)系统具有以下值:

a = 6

b = 4

a + b = 10 (overflow if performed with integers)

如果我们使用无符号转换进行添加,我们将:

int((unsigned)a + (unsigned)b) = (int) ((unsigned)(10)) = -6

要理解原因,我们可以快速检查二进制加法:

a = 0110 ; b = 0100 - first bit is the sign bit for signed int.

0110 +
0100
------
1010

For unsigned int, 1010 = 10。虽然表达方式相同in signed int means -6

因此操作的result确实是< 0

答案 3 :(得分:1)

如果整数是无符号的并且您假设是IA32,则可以执行一些内联​​汇编来检查CF标志的值。我知道,asm可以修剪一下。

int of(unsigned int a, unsigned int b)
{
        unsigned int c;

        __asm__("addl %1,%2\n"
                "pushfl \n"
                "popl %%edx\n"
                "movl %%edx,%0\n"
                :"=r"(c)
                :"r"(a), "r"(b));

        return(c&1);
}

答案 4 :(得分:0)

this page有一些很好的解释。

这是我喜欢的那个页面的简单方法:

Do the addition normally, then check the result (e.g. if (a+23<23) overflow).

答案 5 :(得分:0)

我们知道添加2个数字可能会溢出。 因此,我们可以使用以下方式添加两个数字。

加法概念

假设我们有2个数字&#34; a&#34;和&#34; b&#34;

(A ^ B)+(A和B); 这个等式将给出正确的结果.. 这是三星的专利。

答案 6 :(得分:0)

假设两个恭维表示和8位整数,最高有效位有符号(1表示负数,0表示正数),因为我们知道整数是非负数,这意味着两个整数的最高有效位为0。现在,如果添加这些数字的无符号表示在最高有效位中产生1,则表示加法已溢出,并检查无符号整数在最高有效位中是否为1是检查它是否大于有符号整数,或者你可以将它转换为有符号整数,这将是负数(因为最重要的位是1)

示例8位有符号整数(范围-128到127):

twos compliment of 127 = 0111 1111
twos complement of 1   = 0000 0001

unsigned 127           = 0111 1111
unsigned 1             = 0000 0001
unsigned sum           = 1000 0000

sum为128,这对于无符号整数不是溢出,但对于有符号整数是溢出,最重要的位给它。