大数字的C ++溢出检测(无符号长整型)

时间:2015-04-21 17:02:28

标签: c++ try-catch overflow unsigned-long-long-int

我正在处理大整数(unsigned long long)并需要保护溢出条件。无论是否存在异常,代码都会抛出异常:

try
{
    unsigned long long y = std::numeric_limits<unsigned long long>::max() - 2;
    unsigned long long z = 1;
    int size = - 1;
    if((y+z) ^ y < 0) //If y+z causes overflow its sign will be changed => y and (y+z) will have opposite signs
        throw std::overflow_error("overflow of y+z");
    //int* myarray= new int[size]; VS Debug Library catches it earlier than catch()
    printf("%d\n", y*(y+z));
}
catch(exception& e)
{
    cout << e.what() << endl;
}

由于它已经是最大的数据类型(64位),因此没有空间可以推广到更大的数据类型。

新代码:

try
{
    unsigned long long int y = std::numeric_limits<unsigned long long int>::max() - 2;
    unsigned long long int z = std::numeric_limits<unsigned long long int>::max() / 2;
    unsigned long long delta = std::numeric_limits<unsigned long long int>::max() - y;
    int size = - 1;
    if(z > delta) //If y+z causes overflow its sign will be changed => y and (y+z) will have opposite signs
        throw std::overflow_error("overflow of y+z");
    //int* myarray= new int[size]; VS Debug Library catches it earlier than catch()
    printf("%d\n", (y+z));
}
catch(exception& e)
{
    cout << e.what() << endl;
}

2 个答案:

答案 0 :(得分:3)

y < 0永远都是假的,任何xor 0都会是那个东西(你错过了<的评估优先级高于^吗?)。

因此,除非x + y mod <the max value>恰好等于0,否则你将抛出(并且除非你设计了特定的输入,否则看起来总是在实践中抛出)。

也许您打算做的事情是这样的:if((std::numeric_limits<unsigned long long>::max() - y) < z) throw ...;

答案 1 :(得分:2)

你有两个问题。主要是operator precedence<高于^。这是编译并启用所有警告的一个很好的理由,因为gcc和clang都会给我一个关于这个表达式的警告并建议使用括号!

由编译器评估的表达式实际上是:

if ( (y+z) ^ (y < 0) )

由于y < 0评估为0,所以只是:

if (y+z)

显然是true。但即使你的括号正确,如:

if (((y+z) ^ y) < 0) { ... }

这个表达很简单false。它仍然会有unsigned long long类型,永远不会评估为< 0