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

时间:2011-09-16 23:03:35

标签: c++ math overflow

我有一个sum()功能。 我需要抓住所有的溢出。

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

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

3 个答案:

答案 0 :(得分: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无法解决的问题。

答案 1 :(得分: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;
    }

结果:溢出

答案 2 :(得分:-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 ) );
}