如何在C++中捕获整数溢出?

13 浏览
0 Comments

如何在C++中捕获整数溢出?

这个问题已经有了答案

如何检测无符号整数溢出?

我有一个 sum() 函数。

我需要捕捉所有的溢出。

我搜索了网站但没有找到一个好的方法去做。

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

admin 更改状态以发布 2023年5月22日
0
0 Comments

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

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
0 Comments

正如其他人所说的,如果结果与两个操作数的符号不同,则发生了二进制补码符号溢出。

反之亦然。如果操作数为相同的符号(负数或非负数),并且结果是相反的,那么就不会发生二进制补码符号溢出。

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

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