2011-10-07 104 views
3

可能重複:
Best way to detect integer overflow in C/C++如何檢查溢出是否發生?

這可能是一個菜鳥的問題,但我怎麼能檢查一些溢出影響了我的號碼的價值C.例如,乘以整數時,並等待一個整數結果,如果實際結果大於最大整數值,實際結果會改變(對吧?)。那麼如何判斷是否發生這種情況呢?

+0

所謂的「重複」問題具體是關於* unsigned *值,並且答案反映了這一點 - 而這個問題更籠統,涵蓋了更棘手的簽名案例。 – caf

回答

3

帶符號的整數溢出就像被零除 - 它會導致未定義的行爲,因此您必須檢查是否會在執行潛在溢出操作之前發生。一旦你溢出了,所有的賭注都沒有了 - 你的代碼可以做任何事情。

*_MAX_MIN<limits.h>中定義的宏可以派上用場,但是您需要注意不要在測試本身中調用未定義的行爲。例如,要檢查是否a * b會溢出給int a, b;,你可以使用:

if ((b > 0 && a <= INT_MAX/b && a >= INT_MIN/b) || 
    (b == 0) || 
    (b == -1 && a >= -INT_MAX) || 
    (b < -1 && a >= INT_MAX/b && a <= INT_MIN/b)) 
{ 
    result = a * b; 
} 
else 
{ 
    /* calculation would overflow */ 
} 

(請注意,一個微妙的陷阱,這避免的是,你不能計算INT_MIN/-1 - 這樣的數量不能保證可表示並確實在普通平臺上造成致命的陷阱)。

1

如果結果數小於其中一個輸入。

a + b = c,如果c =a =>溢出。 編輯:要快,這隻適用於無符號整數的加法。

1

如果你的意思是在編程時,你可以調試代碼。

如果您的意思是運行時,您可以添加一些條件,如果它超出限制,請執行一些操作。

當計算的產量超出範圍時,C不知道該做什麼。你必須通過測試操作數來避開這個。

4

C99標準具有本節說明什麼未定義的行爲是:

3.4.3
未定義行爲
行爲,一旦或錯誤數據的使用非便攜式的或錯誤的程序構建體, ,對此,本國際標準沒有要求 注意可能存在未定義的行爲範圍,從完全忽略情況到完全不可預測的 結果,行爲以特定於 環境(有或沒有發佈診斷消息)的文件化方式在翻譯或程序執行期間,終止執行翻譯或執行(發佈診斷消息)。
示例
未定義行爲的一個示例是整數溢出行爲

所以,你幾乎不走運,沒有可行的方法來檢測在一般情況下,事後。
雖然你的編譯器/實現可能有它的擴展/支持,並有技巧來避免這些情況。
看到這個問題的優秀建議:Best way to detect integer overflow in C/C++

1

在一般情況下,只有盯着結果才能發現溢出。但是,您可以執行的操作是檢查操作是否會分開溢出。例如。如果你想檢查是否A * B溢出,其中A和B是INT的,你需要解決的不平等

a * b <= INT_MAX

也就是說,如果一個< = INT_MAX/B,那麼乘法會溢出。

+0

請記住,當你通過'b'將不等式的兩邊分開時,如果'b'爲負,則必須翻轉不等式。另外,不要忘記'b == 0'的可能性。 – caf

1

只要你用無符號整數進行算術運算,或者可以依賴特定於實現的有關簽名整數溢出行爲的特定保證,可以使用各種技巧。

在無符號乘法的情況下,最簡單的是:

unsigned int lhs = something, rhs = something_else; 
unsigned int product = lhs * rhs; 

if (lhs != 0 && product/lhs != rhs) { overflow occurred } 

這是不太可能要快,但它的便攜性。加法的無符號溢出檢查也很簡單 - 選擇其中一個操作數,然後發生溢出,當且僅當總和小於該值時。