如何在c++中捕获整数溢出

How to catch integer overflow in C++?

本文关键字:整数 溢出 c++      更新时间:2023-10-16

我有一个sum()函数。我需要捕捉所有溢出

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

所以…任何想法吗?

如前所述,如果结果与两个操作数的符号不同,则发生补号溢出。

反之也成立。除非操作数的符号相同(负或非负)且结果相反,否则不会发生补码溢出。

不过,我个人更喜欢更直接的方法:

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++中的整型有符号溢出不能保证绕行,因为不需要2的补数运算。有符号整数溢出甚至可能崩溃,尽管这种情况不大可能发生。因此,就语言而言,最好在发生之前停止溢出。c++ 03§5/5:

如果在表达式求值期间,结果没有在数学上定义,或者不在其类型的可表示值范围内,则行为是未定义的,除非该表达式是常量表达式(5.19),在这种情况下,程序是病态的。[注:大多数现有的c++实现忽略整数溢出。]…]

请参阅Boost数字转换库,虽然我不确定它可以为std::numeric_limits不能做任何事情。

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

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 ) );
}

__asm jno notoverflow;

__asm Jo overflow.

在这里使用asm更方便。

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

结果:溢出