J'ai une deuxieme interrogation qui porte sur un cours d'assembleur diffusé sur le site. Dedans est decrit un bug en C et je voudrai savoir ce qu'il en était aujourd'hui avoir des avis dessus:
1 2 3 4 5 6 7
|
"
char ch;
while( (ch = fgetc(fp )) != EOF ) {
/* faire qqch avec ch */
"
} |
"On peut se demander pourquoi est-ce que la fonction renvoie un int puisqu'elle
lit des caractères? La raison est qu'elle renvoie normalement un char
(étendu à une valeur int en utilisant l'extension de zéro). Cependant, il y a
une valeur qu'elle peut retourner qui n'est pas un caractère, EOF. C'est une
macro habituellement dénie comme valant −1. Donc, fgetc() retourne soit
un char étendu à une valeur int (qui ressemble à 000000xx en hexa) soit
EOF (qui ressemble à FFFFFFFF en hexa).
Le problème avec le programme de la Figure 2.2 est que fgetc() renvoie
un int, mais cette valeur est stockée dans un char. Le C tronquera alors
les bits de poids fort pour faire tenir la valeur de l'int dans le char. Le
seul problème est que les nombres (en hexa) 000000FF et FFFFFFFF seront
tous deux tronqué pour donner l'octet FF. Donc, la boucle while ne peut pas
distinguer la lecture de l'octet FF dans le fichier et la fin de ce fichier.
Ce que fait exactement le code dans ce cas change selon que le char est
signé ou non. Pourquoi? Parce que ligne 2, ch est comparé avec EOF. Comme
EOF est un int1, ch sera étendu à un int afin que les deux valeurs comparées
soient de la même taille2. Comme la Figure 2.1 le montrait, le fait qu'une
variable soit signée ou non est très important.
Si le char n'est pas signé, FF est étendu et donne 000000FF. Cette valeur
est comparée à EOF (FFFFFFFF) et est différente. Donc la boucle ne finit
jamais!
So le char est signé, FF est étendu et donne FFFFFFFF. Les deux valeurs
sont alors égale et la boucle se termine. Cependant, comme l'octet FF peut
avoir été lu depuis le fichier, la boucle peut se terminer prématurément.
La solution à ce problème est de défnir la variable ch comme un int,
pas un char. Dans ce cas, aucune troncation ou extension n'est effectuée à
la ligne 2. Dans la boucle, il est sans danger de tronquer la valeur puisque
ch doit alors être réellement un octet." (paragraphe issu du cours)
Partager