2011-09-16 23 views
4

我有sum()函数。 我需要捕获所有溢出。如何在C++中捕捉整数溢出?

我搜索了网站,但没有找到一个好办法。

所以......有什么想法?

+0

取决于你正在求和的东西。提供代码 –

+0

实际上,交叉引用的问题是关于_any的默认数据类型_,尽管主要的例子是关于'float'而不是'int'的任何形式。答案肯定覆盖了一些安全的整数库,因此会帮助提问者。 –

+0

另请参见:[在C/C++中检测整数溢出的最佳方法](http://stackoverflow.com/questions/199333/best-way-to-detect-integer-overflow-in-c-c)。 –

回答

-1

为了发生溢出,两个操作数必须是相同的符号。如果操作数的总和与操作数不同,则发生溢出。

bool overflow(int a, int b) 
{ 
    bool op_same_sign = (a < 0) == (b < 0); 
    bool sum_diff_sign = (a < 0) != (a + b < 0); 
    return op_same_sign && sum_diff_sign; 
} 

更简洁...

bool overflow(int a, int b) 
{ 
    return ((a < 0) == (b < 0) && (a + b < 0) != (a < 0)); 
} 
+0

@Michael:术语整数下溢常被用来描述“INT_MIN”的“溢出”。同样'std :: numeric_limits < float > :: min()'是一个非常小的值,而'std :: numeric_limits < int > :: min()'非常大。 – Potatoswatter

+0

@Patatoswatter - 我们都知道这是不正确的。虽然在这种情况下,我显然是不正确的:) –

+1

这是未定义的行为。 – Ladislav

0

__asm JNO notoverflow;

__asm jo溢出。

使用asm在这里更方便。

int main() 
    { 
     int x = 2147483647; 
     x++; 
     __asm jo overflowed; 
     printf("Not Overflow\n"); 
     if(0) 
     { 
      overflowed: 
      printf("Overflowed!\n"); 
     } 
     return 0; 
    } 

结果:溢出

+0

你能详细说明一下吗?我如何在实践中使用它? – nibot

+0

与goto – iamsleepy

+2

#1相同。不可移植,(这个例子只在x86 32位上溢出)。 #2应该完全用汇编语言编写函数,混合使用c和asm,而不必完全知道目标编译器可能是危险的,因为这个例子中,编译器可以在可以重置溢出标志的数学后面插入代码(可以为gcc工作,但失败intel/llvm)并且可能会根据标记进入编译器(边界检查)而改变。 – Rahly

6

正如其他人所说,如果结果是不同的符号比两个操作数,发生补签署溢出。

反过来也是如此。除非操作数是相同的符号(负或非负)并且结果相反,否则不会发生补码签名溢出。

不过,就个人而言,我更喜欢一个更简单的方法:

int_type a = 12356, b = 98765432; 
if (b > 0 && a > std::numeric_limits<int_type>::max() - b) 
    throw std::range_error("adding a and b would cause overflow"); 

if (b < 0 && a < std::numeric_limits<int_type>::min() - b) 
    throw std::range_error("adding a and b would cause underflow"); 

int_type c = a + b; 

这将赶上符号和无符号溢/下溢,这是很容易看到发生了什么。此外,C++中的整数有符号溢出不保证环绕,因为不需要二进制补码算术。有符号的整数溢出甚至可能会崩溃,尽管不太可能。所以就语言而言,最好在之前停止溢出它发生。 C++ 03§5/ 5:

如果表达式的评估过程中,其结果是不数学上或不在其类型可表示的值的范围限定,该行为是未定义的,除非这样的表达是一个常数表达式(5.19),在这种情况下该程序是不合格的。 [注意:C++的大多数现有实现忽略整数溢出。 ...]

又见Boost Numeric Conversion库,虽然我不知道它可以为这个问题做任何事情,std::numeric_limits不能。

+0

您需要首先断言'b'是非负数,否则再次遇到UB。 –

+0

@BaummitAugen谢谢,修正。这里有一点微妙之处,我希望解决方案完全明显...... – Potatoswatter

+0

差不多,但第二个“if”仍然是错误的。如果'b'是负数,'std :: numeric_limits < int_type > :: min()+ b'仍然是UB。 –