如何在C++中捕获整数溢出?
如何在C++中捕获整数溢出?
这个问题已经有了答案:
我有一个 sum()
函数。
我需要捕捉所有的溢出。
我搜索了网站但没有找到一个好的方法去做。
所以...有什么想法吗?
admin 更改状态以发布 2023年5月22日
为了发生溢出,两个操作数必须是相同的符号。如果两个操作数的和与操作数的符号不同,则发生了溢出。
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 ) ); }
正如其他人所说的,如果结果与两个操作数的符号不同,则发生了二进制补码符号溢出。
反之亦然。如果操作数为相同的符号(负数或非负数),并且结果是相反的,那么就不会发生二进制补码符号溢出。
不过,就我个人而言,我更喜欢更简单明了的方法:
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
无法解决的问题。