Il tuo codice sembra funzionare, perché le conversioni di tipo implicito accidentalmente capita di fare la cosa giusta.
getchar()
restituisce un int
con un valore che rientra nell'intervallo di unsigned char
o è EOF
(che deve essere negativo, di solito è -1). Nota che EOF
non è un personaggio, ma segnala che non ci sono più caratteri disponibili.
Quando si memorizza il risultato da getchar()
in c
, ci sono due possibilità. O il tipo char
può rappresentare il valore, nel qual caso è il valore di c
. Oppure il tipo char
non può rappresentare il valore. In tal caso, non è definito cosa accadrà. I processori Intel tagliano solo i bit alti che non si adattano al nuovo tipo (riducendo efficacemente il valore modulo 256 per char
), ma non dovresti fare affidamento su questo.
Il prossimo passo è confrontare c
con EOF
. Poiché EOF
è un int
, c
verrà convertito anche in int
, preservando il valore memorizzato in c
. Se c
potrebbe memorizzare il valore di EOF
, allora il confronto avrà successo, ma se c
potrebbe non memorizzare il valore, allora il confronto fallirà, perché c'è stata una perdita irrecuperabile di informazioni durante la conversione di EOF
nel tipo char
.
Sembra che il compilatore abbia scelto di rendere il tipo char
firmato e il valore di EOF
abbastanza piccolo da rientrare in char
. Se char
non era firmato (o se hai utilizzato unsigned char
), il tuo test sarebbe fallito, perché unsigned char
non può contenere il valore di EOF
.
Nota anche che c'è un secondo problema con il tuo codice. Poiché EOF
non è un personaggio stesso, ma lo imponi in un tipo char
, è molto probabile che un personaggio là fuori venga interpretato erroneamente come EOF
e per metà dei possibili caratteri non è definito se saranno elaborato correttamente.