Nel linguaggio C, le operazioni aritmetiche con tipi interi possono portare a overflow quando il risultato supera i limiti del tipo rappresentabile, come ad esempio int o unsigned int. La specificità del comportamento in caso di overflow è dettata dagli standard del linguaggio.
L'overflow del tipo firmato (signed overflow) porta a un comportamento indefinito, il che significa che il compilatore ha il diritto di eseguire qualsiasi azione: ignorare l'errore, generare un'eccezione o restituire un risultato imprevedibile. Per i tipi non firmati (unsigned), secondo lo standard C, il comportamento in caso di overflow è definito: si verifica un wraparound modulo la dimensione del tipo.
Per i numeri unsigned, il risultato dell'overflow è facilmente prevedibile, ad esempio, UINT_MAX + 1 == 0. Per i numeri signed, si raccomanda di controllare i limiti del tipo prima delle operazioni utilizzando macro da <limits.h> o di usare strumenti di analisi statica. I moderni compilatori e strumenti possono rilevare potenziali overflows.
Esempio di codice:
#include <stdio.h> #include <limits.h> int add_with_check(int a, int b) { if (a > 0 && b > INT_MAX - a) { printf("Si verificherà un overflow! "); return -1; } return a + b; } int main() { int x = INT_MAX, y = 1; printf("Risultato: %d ", add_with_check(x, y)); unsigned int ux = UINT_MAX; printf("Overflow unsigned: %u ", ux + 1); return 0; }
Caratteristiche chiave:
<limits.h> per ottenere le dimensioni dei tipiL'overflow di un tipo unsigned è un errore?
No, questo comportamento è definito dallo standard ed è equivalente a un wraparound. Ad esempio, (unsigned int)UINT_MAX + 1 == 0 è sempre vero.
Si può contare sul fatto che in caso di overflow di un int il risultato semplicemente "supererà" INT_MIN?
No, tale comportamento non è garantito e non è standardizzato, è un comportamento indefinito. Potrebbe crasher, restituire un valore non corretto (diverso su piattaforme) o essere ottimizzato in modo imprevedibile dal compilatore.
Si può contare sul comportamento che un int sia sempre in complemento a due?
Sebbene l'hardware moderno utilizzi quasi sempre il «complemento a due» per rappresentare int signed, il linguaggio C non richiede standardmente questo, quindi un codice con overflow non sarà portabile.
Somma di numeri int senza controllo dei limiti — l'overflow con grandi dati porta a calcoli non validi.
Vantaggi:
Svantaggi:
Prima di tutte le operazioni aritmetiche viene effettuato un controllo sull'overflow utilizzando macro e funzioni. Utilizzo di unsigned dove il wraparound è consentito.
Vantaggi:
Svantaggi: