L’overflow avviene quando il risultato di un’operazione supera l’intervallo rappresentabile con i bit disponibili: il valore “gira” (wrap-around) producendo un risultato sbagliato. Riconoscerlo è cruciale per la correttezza dei programmi. Questa scheda allena il rilevamento dell’overflow in complemento a due e senza segno.
1. Overflow in complemento a due
Esercizio. Su 8 bit (compl. a 2, intervallo [-128,127]), calcolare 100+50 e verificare l’overflow.
100=01100100_2, 50=00110010_2:
01100100+00110010=10010110_2.
Il risultato 10010110_2 ha MSB = 1 → interpretato come negativo: vale -106. Ma 100+50=150>127: overflow. Sommando due positivi è uscito un negativo: segnale inequivocabile di overflow.
2. Regola del segno per l’overflow
Esercizio. Enunciare la regola per rilevare l’overflow in complemento a due.
L’overflow in complemento a due si verifica quando:
\text{due operandi di segno uguale danno un risultato di segno opposto.}
- positivo + positivo = negativo → overflow;
- negativo + negativo = positivo → overflow;
- segni diversi → mai overflow (il risultato sta sempre nell’intervallo).
Tecnicamente: overflow se il riporto entrante e quello uscente dal bit di segno differiscono.
3. Riporto contro overflow
Esercizio. Distinguere riporto (carry) e overflow nella somma 11111111_2+00000001_2 su 8 bit.
Il risultato è 1\,00000000: c’è un riporto oltre l’8° bit.
- In interpretazione senza segno (255+1): overflow (256 non rappresentabile su 8 bit).
- In interpretazione con segno (-1+1=0): nessun overflow, risultato corretto 0.
Riporto e overflow sono concetti diversi: il carry riguarda i senza segno, l’overflow i numeri con segno. La stessa operazione può avere carry ma non overflow.
4. Overflow nei numeri senza segno
Esercizio. Su 8 bit senza segno (intervallo [0,255]), calcolare 200+100.
200+100=300>255\ \Rightarrow\ \text{overflow senza segno}.
Il risultato gira: 300-256=44. La CPU produce 44 (i 9 bit reali sono 100101100, scartando il 9°). Per i senza segno l’overflow è segnalato dal carry oltre l’ultimo bit.
5. Wrap-around
Esercizio. Su 8 bit senza segno, cosa restituisce 255+1 e perché?
255+1=256\equiv0\ (\text{mod }256).
Il risultato “gira” a 0: è il wrap-around. L’aritmetica su n bit è in realtà modulo 2^n. È il bug classico dei contatori che azzerano dopo il massimo (es. il “millennium bug” e gli overflow dei timer).
6. Conseguenze pratiche e prevenzione
Esercizio. Come si previene o rileva l’overflow in pratica?
Strategie tipiche:
- usare tipi più larghi: passare da 8 a 16 o 32 bit estende l’intervallo (es. da \pm127 a \pm32767);
- controllare i flag di stato: le CPU espongono un flag di overflow (V) e di carry (C) dopo ogni operazione;
- verificare prima dell’operazione: controllare che gli operandi non portino fuori intervallo.
Ignorare l’overflow produce risultati silenziosamente errati: è una delle cause più insidiose di bug e vulnerabilità.
7. Overflow negativo
Esercizio. Su 8 bit in complemento a due, verificare se -100+(-50) produce overflow.
L’intervallo è [-128,127]. Il risultato matematico è:
quindi il risultato non è rappresentabile. Vediamolo sui bit:
Somma:
Scartando il nono bit resta 01101010_2=106, positivo. Due negativi hanno prodotto un positivo: è overflow. Il pattern 01101010 non va letto come risultato valido della somma con segno.
8. Overflow nella sottrazione
Esercizio. Su 8 bit in complemento a due, valutare 100-(-50).
La sottrazione diventa una somma:
Il valore 150 supera il massimo 127, quindi ci sarà overflow. In bit:
e la somma è:
Il risultato ha segno negativo, pur provenendo da due addendi positivi. Regola operativa: nella sottrazione a-b, prima si considera a+(-b) e poi si applica la stessa regola dei segni dell’addizione.
9. Controllo preventivo senza calcolare la somma
Esercizio. Come controllare se a+b può andare in overflow prima di sommare, usando interi con segno su 8 bit?
Per l’intervallo [-128,127]:
- se b>0, serve a\le127-b;
- se b<0, serve a\ge-128-b;
- se b=0, l’operazione è sempre sicura.
Esempio: per a=90, b=40:
Poiché 90>87, la somma 90+40 andrà in overflow. Questo controllo è usato nelle librerie sicure quando il linguaggio o la piattaforma non garantiscono eccezioni automatiche sull’overflow.
10. Aritmetica saturata contro wrap-around
Esercizio. Su 8 bit senza segno, confrontare il risultato di 250+20 con wrap-around e con saturazione.
Il risultato matematico è:
Su 8 bit senza segno il massimo è 255.
- Wrap-around: si lavora modulo 256, quindi 270-256=14.
- Saturazione: si blocca il risultato al massimo rappresentabile, quindi 255.
Le CPU general purpose usano normalmente aritmetica modulo; molte istruzioni SIMD per audio, immagini e segnali offrono anche aritmetica saturata, perché in quei domini è preferibile troncare al massimo piuttosto che far girare il valore a un numero piccolo.
Errori comuni
- Confondere carry e overflow. Il carry riguarda i senza segno, l’overflow i numeri con segno: sono flag distinti.
- Pensare che segni diversi diano overflow. Sommando un positivo e un negativo l’overflow è impossibile in complemento a due.
- Dimenticare che la sottrazione è una somma. Per a-b va analizzata l’addizione a+(-b), con le stesse regole dell’overflow con segno.
- Ignorare il wrap-around. L’aritmetica a n bit è modulo 2^n: superato il massimo si riparte da zero, non si “blocca”.
- Affidarsi a tipi troppo piccoli. Per somme di valori grandi servono tipi più larghi: l’overflow silenzioso è una fonte di bug gravi.