2010-04-13 4 views
20

Eventuali duplicati:
Best way to detect integer overflow in C/C++Come controllare l'overflow dei numeri interi in C?

C'è (1):

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

e (2):

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

whichs è prefe rred o c'è un modo migliore.

+0

In realtà il duplicato non è un duplicato a tutti, sta parlando di 'unsigned' che sono ben definiti semantica avvolgenti, mentre traboccante un intero con segno è un comportamento indefinito in C. –

+2

Non v'è alcuna necessità di controllare sia 'sum

risposta

-5

Devi solo controllare uno di loro. Se x + y trabocca, sarà inferiore sia a x che a y. Quindi:

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

dovrebbe essere sufficiente.

Il seguente sito ha un sacco di roba su integer overflow:

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

Se si desidera gestire i numeri negativi, può essere espansa:

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

Cosa succede se "y" è negativo? –

+1

Il poster originale ha specificato numeri interi non negativi, ma ho aggiunto il codice per gestire i numeri negativi. – clahey

+18

Questo non è corretto - una volta 'x + y' ha tracimato, il programma ha un comportamento indefinito.Devi * controllare * prima di eseguire effettivamente l'operazione di overflow, proprio come fai per la divisione di interi per zero. – caf

6

si può davvero unico controllo per overflow con unsigned numeri interi e aritmetici:

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

Il comportamento di troppo pieno con interi con segno non è definito in C, ma sulla maggior parte delle macchine è possibile utilizzare

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

questo non funziona su macchine che utilizzano qualsiasi tipo di saturare aritmetica

+4

Il controllo dell'overflow dopo il fatto con interi con segno non è corretto. È un comportamento indefinito, quindi i compilatori ottimizzano felicemente i controlli senza passare un interruttore come '-fwrapv' per abilitare il wrapping con segno come estensione del linguaggio. Non è solo un problema di portabilità tra architetture. – strcat

+1

È inoltre possibile controllare l'overflow per interi con segno. Vedi https://www.securecoding.cert.org/confluence/display/c/INT32-C.+Ensure+that+operations+on+signed+integers+do+not+result+in+overflow – sbhatla

47

integer overflow è il esempio canonico di "comportamento indefinito" in C (osservando che le operazioni su interi non firmati non si sovrappongono mai, sono invece definite per il wrap-around). Ciò significa che, una volta eseguito x + y, se è in overflow, sei già in difficoltà. È troppo tardi per fare qualche controllo - il tuo programma potrebbe essersi già schiantato. Pensa ad un controllo per divisione per zero - se aspetti fino a dopo che la divisione è stata eseguita per controllare, è già troppo tardi.

Quindi questo implica che il metodo (1) è l'unico modo corretto per farlo. Per max, è possibile utilizzare INT_MAX da <limits.h>.

Se x e/o possono essere negativi, le cose sono più difficili: è necessario eseguire il test in modo che il test non possa causare un overflow.

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

Se sei andando a downvote, è considerato cortese lasciare un commento che spieghi ciò che ritieni sia inutile o sbagliato. – caf

+0

Btw, puoi commentare le prestazioni di questa soluzione rispetto ad altre soluzioni alternative? – Pacerier

+6

Non ha molto senso confrontare le prestazioni con una soluzione errata. Quale altra soluzione corretta avevi in ​​mente? – caf