2011-09-16 20 views
4

我有sum()函數。 我需要捕獲所有溢出。如何在C++中捕捉整數溢出?

我搜索了網站,但沒有找到一個好辦法。

所以......有什麼想法?

+0

取決於你正在求和的東西。提供代碼 –

+0

實際上,交叉引用的問題是關於_any的默認數據類型_,儘管主要的例子是關於'float'而不是'int'的任何形式。答案肯定覆蓋了一些安全的整數庫,因此會幫助提問者。 –

+0

另請參見:[在C/C++中檢測整數溢出的最佳方法](http://stackoverflow.com/questions/199333/best-way-to-detect-integer-overflow-in-c-c)。 –

回答

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

@Michael:術語整數下溢常被用來描述「INT_MIN」的「溢出」。同樣'std :: numeric_limits < float > :: min()'是一個非常小的值,而'std :: numeric_limits < int > :: min()'非常大。 – Potatoswatter

+0

@Patatoswatter - 我們都知道這是不正確的。雖然在這種情況下,我顯然是不正確的:) –

+1

這是未定義的行爲。 – Ladislav

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

結果:溢出

+0

你能詳細說明一下嗎?我如何在實踐中使用它? – nibot

+0

與goto – iamsleepy

+2

#1相同。不可移植,(這個例子只在x86 32位上溢出)。 #2應該完全用匯編語言編寫函數,混合使用c和asm,而不必完全知道目標編譯器可能是危險的,因爲這個例子中,編譯器可以在可以重置溢出標誌的數學後面插入代碼(可以爲gcc工作,但失敗intel/llvm)並且可能會根據標記進入編譯器(邊界檢查)而改變。 – Rahly

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不能。

+0

您需要首先斷言'b'是非負數,否則再次遇到UB。 –

+0

@BaummitAugen謝謝,修正。這裏有一點微妙之處,我希望解決方案完全明顯...... – Potatoswatter

+0

差不多,但第二個「if」仍然是錯誤的。如果'b'是負數,'std :: numeric_limits < int_type > :: min()+ b'仍然是UB。 –