J'ai lu dans le livre du langage de programmation C de Dennis Ritchie qui int
doit être utilisé pour qu'une variable contienne EOF - pour la rendre suffisamment grande pour qu'elle puisse contenir une valeur EOF - non char
. Mais le code suivant fonctionne bien:
#include<stdio.h>
main() {
char c;
c=getchar();
while(c!=EOF) {
putchar(c);
c=getchar();
}
}
Lorsqu'il n'y a plus d'entrée, getchar
renvoie EOF. Et dans le programme ci-dessus, la variable c
, de type char, est capable de la maintenir avec succès.
Pourquoi ça marche? Selon l'explication dans le livre mentionné ci-dessus, le code ne devrait pas fonctionner.
0xff
. Le stockage du résultat degetchar()
dansint
résout ce problème. Votre question est essentiellement la même que la question 12.1 de la FAQ comp.lang.c , qui est une excellente ressource. (En outre, celamain()
devrait l'êtreint main(void)
, et cela ne ferait pas de mal d'en ajouter unreturn 0;
avant la clôture}
.)Réponses:
Votre code semble fonctionner, car les conversions de types implicites se produisent accidentellement pour faire la bonne chose.
getchar()
renvoie unint
avec une valeur qui correspond à la plage deunsigned char
ou estEOF
(qui doit être négative, généralement -1). Notez queEOF
lui - même n'est pas un caractère, mais un signal qu'il n'y a plus de caractères disponibles.Lors de l'enregistrement du résultat depuis
getchar()
inc
, il existe deux possibilités. Soit le typechar
peut représenter la valeur, auquel cas il s'agit de la valeur dec
. Ou le typechar
ne peut pas représenter la valeur. Dans ce cas, il n'est pas défini ce qui se passera. Les processeurs Intel coupent simplement les bits élevés qui ne rentrent pas dans le nouveau type (réduisant effectivement la valeur modulo 256 pourchar
), mais vous ne devriez pas vous fier à cela.L'étape suivante consiste à comparer
c
avecEOF
. CommeEOF
c'est le casint
,c
sera également converti en unint
, préservant la valeur stockée dansc
. Sic
peut stocker la valeur deEOF
, la comparaison réussira, mais sic
elle ne peut pas stocker la valeur, la comparaison échouera, car il y a eu une perte irrécupérable d'informations lors de la conversionEOF
en typechar
.Il semble que votre compilateur ait choisi de faire le
char
type signé et la valeur deEOF
suffisamment petite pour tenirchar
. Sichar
vous n'aviez pas signé (ou si vous l'aviez utiliséunsigned char
), votre test aurait échoué, carunsigned char
il ne peut pas contenir la valeur deEOF
.Notez également qu'il existe un deuxième problème avec votre code. Comme ce
EOF
n'est pas un personnage lui-même, mais que vous le forcez dans unchar
type, il y a très probablement un personnage qui est mal interprété comme étantEOF
et pour la moitié des caractères possibles, il n'est pas défini s'ils seront traités correctement.la source
char
valeurs en dehors de la plageCHAR_MIN
..CHAR_MAX
volonté est nécessaire pour produire une valeur définie par l'implémentation, produire un modèle de bits que l'implémentation définit comme une représentation d'interruption, ou élever un signal défini par l'implémentation. Dans la plupart des cas, les implémentations devraient passer par beaucoup de travail supplémentaire pour faire autre chose que la réduction du complément à deux. Si les membres du Comité des normes souscrivaient à l'idée que les compilateurs devraient être encouragés à mettre en œuvre des comportements compatibles avec ceux de la plupart des autres compilateurs en l'absence de raisons de faire autrement ...(signed char)x
devrait être considéré comme plus clair et tout aussi sûr que((unsigned char)x ^ CHAR_MAX+1))-(CHAR_MAX+1)
.) En l'état, je ne vois aucune probabilité de les compilateurs implémentant tout autre comportement conforme à la norme actuelle; le seul danger serait que la Norme soit modifiée pour rompre le comportement dans l'intérêt supposé de "l'optimisation".int i=129; signed char c=i;
est l'un de ces comportements. Relativement peu de processeurs ont une instruction qui ferait lac
mêmei
chose dans la plage de -127 à +127 et produirait un mappage cohérent d'autres valeurs dei
à des valeurs dans la plage de -128 à +127 qui différaient de la réduction du complément à deux, ou. ..