2010-04-13 34 views
20

Powiel możliwe:
Best way to detect integer overflow in C/C++Jak sprawdzić liczbę całkowitą w C?

tam (1):

// assume x,y are non-negative 
if(x > max - y) error; 

A (2):

// assume x,y are non-negative 
int sum = x + y; 
if(sum < x || sum < y) error; 

whichs jest prefe rred czy jest lepszy sposób?

+0

Właściwie duplikat nie jest duplikatem w ogóle, to mówimy o 'unsigned' które dobrze zdefiniowanych wraparound semantykę, natomiast przepełnione podpisaną całkowitą zachowanie jest niezdefiniowane w C. –

+2

Nie ma potrzeby, by sprawdzić zarówno 'suma

Odpowiedz

-5

Trzeba tylko sprawdzić jedną z nich. Jeśli przepełnienie x + y będzie mniejsze niż x i y. W związku z tym:

int sum = x + y; 
if (sum < x) error; 

powinny wystarczyć.

Poniższa strona ma kilka rzeczy o całkowitej overflow:

http://www.fefe.de/intof.html

Jeśli chcesz obsługiwać liczby ujemne, to może być rozszerzony:

int sum = x + y; 
if (y >= 0) { 
    if (sum < x) error; 
} else { 
    if (sum > x) error; 
} 
+1

Co jeśli 'y' jest ujemny? –

+1

Oryginalny plakat określający nieujemne liczby całkowite, ale dodałem kod do obsługi liczb ujemnych. – clahey

+18

To nie jest poprawne - po przekroczeniu 'x + y' program ma niezdefiniowane zachowanie.Masz * do sprawdzenia przed wykonaniem przepełnienia operacji - tak samo jak w przypadku dzielenia całkowitoliczbowego przez zero. – caf

6

naprawdę można tylko czek dla przepełnienia z liczbami całkowitymi unsigned i arithmatic:

unsigned a,b,c; 
a = b + c; 
if (a < b) { 
    /* overflow */ 
} 

Zachowanie przelewem z podpisanych liczb całkowitych jest niezdefiniowana w C, ale na większości komputerów można użyć

int a,b,c; 
a = b + c; 
if (c < 0 ? a > b : a < b) { 
    /* overflow */ 
} 

To nie będzie działać na komputerach, które korzystają z wszelkiego rodzaju nasycania arytmetycznych

+4

Sprawdzanie przepełnienia po fakcie ze znakami całkowitymi jest nieprawidłowe. Jest to niezdefiniowane zachowanie, więc kompilatory z przyjemnością optymalizują sprawdzenia bez przekazywania przełącznika takiego jak "-fwrapv", aby umożliwić podpisanie zawijania jako rozszerzenie języka. To nie tylko kwestia przenośności na różnych architekturach. – strcat

+1

Można również sprawdzić przepełnienie dla liczb całkowitych ze znakiem. Zobacz https://www.securecoding.cert.org/confluence/display/c/INT32-C.+Ensure+that+operations+on+signs+integers+do+nie+wyników+w+przepływu – sbhatla

47

Integer jest przepełnienie kanoniczny przykład "niezdefiniowanego zachowania" w C (zauważając, że operacje na liczbach całkowitych bez znaku nigdy się nie przepełniają, są one zdefiniowane jako zawijane zamiast). Oznacza to, że po wykonaniu usługi x + y, jeśli zostanie przepełniony, zostaniesz już zablokowany. Jest już za późno na sprawdzanie - Twój program mógł się już rozbić. Pomyśl o tym, jak o dzieleniu przez zero - jeśli poczekasz, aż podział zostanie wykonany, by sprawdzić, jest już za późno.

Oznacza to, że metoda (1) jest jedyną właściwą metodą. W przypadku max można użyć INT_MAX z <limits.h>.

Jeśli x i/lub y może być ujemny, to rzeczy są trudniejsze - należy wykonać test w taki sposób, aby sam test nie mógł spowodować przepełnienia.

if ((y > 0 && x > INT_MAX - y) || 
    (y < 0 && x < INT_MIN - y)) 
{ 
    /* Oh no, overflow */ 
} 
else 
{ 
    sum = x + y; 
} 
+5

Jeśli jesteś zamierzamy zabrać głos, uprzejmie jest zostawić komentarz wyjaśniający, co uważasz za nieprzydatne lub złe. – caf

+0

Btw, czy możesz wypowiedzieć się na temat wydajności tego rozwiązania w porównaniu do innych alternatywnych rozwiązań? – Pacerier

+6

Nie ma sensu porównywać wydajności z nieprawidłowym rozwiązaniem. Jakie inne prawidłowe rozwiązanie miałeś na myśli? – caf

Powiązane problemy