Conversioni Aritmetiche
Capita spesso di combinare tipi aritmetici diversi (es. sommare un int con un double). In questi casi, il C applica delle regole di conversione rigorose.
Conversioni Esplicite (Cast)
Section titled “Conversioni Esplicite (Cast)”Il Cast ti permette di forzare manualmente il tipo di un’espressione mettendo il nuovo tipo tra parentesi:
int num_i = 5;double num_d = (double)num_i; // Conversione esplicitaConversioni Implicite
Section titled “Conversioni Implicite”Spesso il compilatore effettua queste conversioni “dietro le quinte”. Per farlo segue un set di regole note come Usual Arithmetic Conversions:
- Integer Promotions (Promozioni Intere): I tipi interi piccoli (come
chareshort) vengono sempre “promossi” automaticamente adint(ounsigned int) prima di fare somme, moltiplicazioni o valutare condizioni logiche. Questo previene gli overflow sulle variabili a 8 o 16 bit. - Bilanciamento: Quando i due operandi sono di tipo diverso, il tipo più “debole” (di rango inferiore) viene convertito in quello più “forte”.
int+double→ Il C converte l’intindoublee fa la somma su duedouble.signed int+unsigned int→ L’operando signed viene “forzato” a diventareunsigned int.
Il Pericolo delle Conversioni Implicite
Section titled “Il Pericolo delle Conversioni Implicite”Guardiamo un esempio spaventoso ma comune. Immagina di confrontare un -1 con il valore massimo UINT_MAX:
unsigned int ui = UINT_MAX;signed char c = -1;
if (c == ui) { printf("Magia, sono uguali!");}Perché stampa che sono uguali?
- Promozione:
cè unosigned char(-1). Viene promosso asigned int(-1). - Bilanciamento: Stiamo confrontando un
signed intcon ununsigned int. La regola dice che l’intero con segno deve convertirsi in intero senza segno. - Il valore
-1, letto come se fosse “senza segno” (quindi con tutti i bit a 1 nel complemento a due), corrisponde in memoria al valore binario equivalente aUINT_MAX. I due numeri combaciano a livello di bit!
💻 Esercizio Pratico
Section titled “💻 Esercizio Pratico”Ecco un esercizio su una pericolosa conversione implicita.
L’obiettivo di questo codice è scorrere un array. Tuttavia c’è una pericolosa combinazione di tipi: sizeof restituisce un tipo unsigned, che potrebbe far nascere dei bug con cicli che decrementano verso zero.