2009-10-27 50 views

回答

6

首先,溢出簽署計算導致未定義行爲C.

其次,忘記了UB一秒鐘,堅持2的補機的典型的溢出行爲:溢出是導致這一事實表明「向第一個操作數「錯誤的方向」移動,即當結果大於第一個操作數的正的第二個操作數(或小於第一個操作數的負的第二個操作數)時。

在你的情況

int one, two; 

int result = two - one; 
if ((result < two) != (one > 0)) 
    printf("overflow"); 
+1

如果'int result = two - one;'溢出(或下溢),您將進入Undefined Behavior land併發生任何事情。 – pmg 2009-10-27 21:49:20

+0

這是我在迴應的第一句中明確指出的內容。 (儘管術語「下溢」在傳統意義上不適用於此)。 – AnT 2009-10-27 21:53:21

+0

我喜歡這個答案,但正如你所記錄的那樣 - 未定義的行爲。如果可以安全地假設結果會在'錯誤的方向'上'移動'? – 2009-10-27 21:56:52

1

您可以以更高的精度進行比較。假設你有32位整數。您可以將它們提升爲64位整數,然後減去,然後將該結果與自身進行比較,轉換爲32位,然後再轉換爲64位。

我不會int做這種方式,因爲語言不給你保證在大小......也許int32_tint64_t<inttypes.h>(從C99)。

如果你在Windows上使用可以使用ULongSub()等,它會在溢出時返回一個錯誤代碼。

+0

如果我做這種情況下,32位: 0x7FFFFFFF的 - 爲0x80000000 = 0xffffffff的 在64位,我得到0xffffffffffffffff ,因此我看不出有任何溢出(它應該是,雖然這是錯誤的答案)。 – Murph 2009-10-27 21:09:38

+0

忘了提及這隻使用無符號數量真的有效...... – asveikau 2009-10-28 01:38:00

10

你需要趕上過低(或下溢)它發生之前。一旦發生這種情況,你在未定義的行爲土地和所有投注都關閉。

#include <limits.h> 
#include <stdio.h> 

int sum_invokes_UB(int a, int b) { 
    int ub = 0; 
    if ((b < 0) && (a < INT_MIN - b)) ub = 1; 
    if ((b > 0) && (a > INT_MAX - b)) ub = 1; 
    return ub; 
} 

int main(void) { 
    printf("(INT_MAX-10) + 8: %d\n", sum_invokes_UB(INT_MAX - 10, 8)); 
    printf("(INT_MAX-10) + 100: %d\n", sum_invokes_UB(INT_MAX - 10, 100)); 
    printf("(INT_MAX-10) + INT_MIN: %d\n", sum_invokes_UB(INT_MAX - 10, INT_MIN)); 
    printf("100 + INT_MIN: %d\n", sum_invokes_UB(100, INT_MIN)); 
    printf("-100 + INT_MIN: %d\n", sum_invokes_UB(-100, INT_MIN)); 
    printf("INT_MIN - 100: %d\n", sum_invokes_UB(INT_MIN, -100)); 
    return 0; 
}