来自C陷阱和陷阱
如果a和b是两个整数变量,则称为非负数 测试
a+b
是否可能溢出使用:if ((int) ((unsigned) a + (unsigned) b) < 0 ) complain();
我没有得到如何将两个整数的总和与零进行比较会让你知道有溢出?
答案 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,这对于无符号整数不是溢出,但对于有符号整数是溢出,最重要的位给它。