有符號整數溢位

根據 C99 和 C11 的第 6.5 / 5 段,如果結果不是表示式型別的可表示值,則表示式的求值會產生未定義的行為。對於算術型別,這稱為溢位。無符號整數運算不會溢位,因為第 6.2.5 / 9 段適用,導致任何超出範圍的無符號結果減少到範圍內值。但是,對於有符號整數型別沒有類似的規定 ; 這些可以並且確實溢位,產生未定義的行為。例如,

#include <limits.h>      /* to get INT_MAX */

int main(void) {
    int i = INT_MAX + 1; /* Overflow happens here */
    return 0;
}

大多數此類未定義行為的例項更難以識別或預測。原則上,溢位可以來自對有符號整數的任何加法,減法或乘法運算(取決於通常的算術轉換),其中沒有有效的界限或運算元之間的關係以防止它。例如,這個功能:

int square(int x) {
    return x * x;  /* overflows for some values of x */
}

是合理的,並且對於足夠小的引數值它是正確的,但是對於較大的引數值,它的行為是未定義的。你無法僅根據函式判斷呼叫它的程式是否會顯示未定義的行為。這取決於他們傳遞給它的論據。

另一方面,請考慮溢位安全有符號整數運算的這個簡單示例:

int zero(int x) {
    return x - x;  /* Cannot overflow */
}

減法運算子的運算元之間的關係確保減法永不溢位。或者考慮這個更實際的例子:

int sizeDelta(FILE *f1, FILE *f2) {
    int count1 = 0;
    int count2 = 0;
    while (fgetc(f1) != EOF) count1++;  /* might overflow */
    while (fgetc(f2) != EOF) count2++;  /* might overflow */

    return count1 - count2; /* provided no UB to this point, will not overflow */
}

只要計數器不單獨溢位,最後減法的運算元都將是非負的。任何兩個這樣的值之間的所有差異都可以表示為 int