2016-04-28 30 views
7

Czytając komentarze do this question, natknąłem się na link do comp.lang.c FAQ która pokazuje „starannego funkcję dodawania”, która rzekomo wykrywa całkowitą przepełnienie:Czy ta funkcja do wykrywania przekroczenia liczby całkowitej rzeczywiście działa?

int 
chkadd(int a, int b) 
{ 
    if (INT_MAX - b < a) { 
     fputs("int overflow\n", stderr); 
     return INT_MAX; 
    } 
    return a + b; 
} 

Jak to nie przepełnienia jeśli b == -1? Jeśli założenie jest takie, że a i b są zarówno dodatnie, dlaczego zamiast tego są one int, a nie ?

+2

ponieważ 'INT_MAX - (-1)' jest równe 'INT_MIN'? – ddz

+2

Podpisano 'int' ** może ** wrap: ale jest to zachowanie * niezdefiniowane *. –

+1

Zakłada, że ​​'a' i' b' są dodatnie. Przydatny do konwersji łańcuchów na 'int' podczas sprawdzania przepełnienia. – user3386109

Odpowiedz

1

Prawdopodobnie tylko to przeoczyli. Additional links na stronie FAQ wydaje się zawierać bardziej poprawny kod.

+1

A te zawiedzie jeśli 'b == INT_MIN', ale przynajmniej o tym wspominają. Domyślam się, że to nie jest tak łatwe, jak oni udają, co jest także moim doświadczeniem ... – zennehoy

+0

Tak samo mówią w "poprawnym kodzie": (Uwaga: wszystkie te funkcje dzielą jeden błąd: mogą zawieść, jeśli zostaną wywołane na największa ujemna liczba całkowita, INT_MIN.). – user3078414

4

OP stwierdził, że INT_MAX - b może przepełnić się, powodując, że pozostały kod jest nieprawidłowy dla właściwego wykrycia przepełnienia. To nie działa.

if (INT_MAX - b < a) { // Invalid overflow detection 

metodę wykrywania przepełnienia bez UB następująco:

int is_undefined_add1(int a, int b) { 
    return (a < 0) ? (b < INT_MIN - a) : (b > INT_MAX - a); 
} 

dlaczego uczynić je int zamiast unsigned int w pierwszej kolejności?

Zmiana na unsigned nie rozwiązuje problemu w ogólnym. Zakres unsigned: [0...UINT_MAX] może być o połowę większy niż w przypadku int: [INT_MIN...INT_MAX]. IOWs: INT_MAX == UINT_MAX. Takie systemy są obecnie rzadkością. IAC, zmiana typów nie jest wymagana, ponieważ jest kodowana z is_undefined_add1().

Powiązane problemy