ProgrammazioneSviluppatore C

Quali sono le regole di conversione dei tipi (type conversion, type promotion) applicate nelle espressioni nel linguaggio C? Fornire esempi di errori inaspettati e soluzioni.

Supera i colloqui con l'assistente IA Hintsage

Risposta

Nel linguaggio C, nelle espressioni spesso avvengono conversioni di tipo (type promotion, type conversion), regolamentate dallo standard:

  • Promozione degli interi: tipi di menor dimensione (ad esempio, char, short) vengono automaticamente convertiti in int o unsigned int prima delle operazioni aritmetiche.
  • Conversioni aritmetiche abituali: se gli operandi hanno tipi diversi, vengono convertiti nel tipo "più ampio" in conformità a regole stabilite.
  • Nelle operazioni miste con tipi firmati e non firmati, il risultato potrebbe cambiare inaspettatamente a causa della conversione.

Esempio:

unsigned short a = 65535; signed short b = -1; printf("%d\n", a + b); // dipende dalla conversione!

Raccomandazione: presta attenzione ai tipi degli operandi, specialmente quando lavori con operazioni bit, lunghezze di array, indici, e evita la mescolanza implicita di tipi firmati e non firmati.

Domanda insidiosa

Cosa stamperà il seguente frammento?

unsigned int u = 1; int i = -2; printf("%d\n", u + i);

Risposta: La variabile i sarà convertita in unsigned int, il valore finale diventerà molto grande, poiché il risultato sotto al cofano è: 1U + (unsigned int)-2U, che darà un numero vicino a UINT_MAX (4294967295). Sarà stampato un numero negativo solo se printf formatta come int, altrimenti spazzatura.

Esempi di errori reali a causa della mancata conoscenza delle sfumature dell'argomento


Storia

Nel calcolo delle medie di intensità di un'immagine sono stati scambiati int e unsigned int. I valori negativi erano erroneamente traslati attraverso unsigned e davano numeri giganteschi, causando un overflow del buffer dell'immagine.


Storia

Nella firmware incorporata calcolavano la lunghezza della stringa tramite size_t, mentre indicizzavano l'array tramite int. Nella verifica della condizione di uscita dall'array confrontavano int i >= size_t len, il che rompeva la logica per stringhe lunghe e provocava bug nel confronto di tipi diversi (size_t — unsigned).


Storia

Un sviluppatore in un progetto finanziario calcolava il resto della divisione per numeri negativi tramite %, dimenticando che il segno del risultato per operandi negativi dipende dall'implementazione. In un ambiente il risultato era positivo, in un altro — negativo, causando occasionalmente che i calcoli "saltassero".