2015-04-21 129 views
0

我正在處理大整數(無符號long long)並需要防範溢出條件。無論代碼拋出異常,如果有實際上是一個:大數字的C++溢出檢測(無符號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; 
} 
+0

相關:http://stackoverflow.com/questions/199333/how-to-detect-integer-overflow-in-c-c – NathanOliver

回答

3

y < 0將永遠是假的,什麼異或0永遠是那件事(你有沒有錯過<在比^更高的優先級進行評估?)。

因此,除非x + y mod <the max value>碰巧等於0,你會拋出(可能似乎總是拋出實踐,除非你設法具體的輸入)。

也許你的意思做的是這樣的:if((std::numeric_limits<unsigned long long>::max() - y) < z) throw ...;

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

+0

謝謝。我改變了代碼(見原文)。如果你知道一個巧妙的技巧可以請發帖: – Vectorizer

+0

查看原文。 – Vectorizer