Leí en el libro The C Programming Language de Dennis Ritchie que int
debe usarse para que una variable contenga EOF, para que sea lo suficientemente grande como para que pueda contener el valor EOF, no char
. Pero el siguiente código funciona bien:
#include<stdio.h>
main() {
char c;
c=getchar();
while(c!=EOF) {
putchar(c);
c=getchar();
}
}
Cuando no hay más entrada, getchar
devuelve EOF. Y en el programa anterior, la variable c
, con el tipo char, puede mantenerlo con éxito.
¿Por qué funciona esto? Según la explicación en el libro mencionado anteriormente, el código no debería funcionar.
0xff
. Almacenar el resultado degetchar()
unint
resuelve ese problema. Su pregunta es esencialmente la misma que la pregunta 12.1 en las preguntas frecuentes de comp.lang.c , que es un excelente recurso. (Además,main()
debería serint main(void)
, y no estaría de más agregar unreturn 0;
antes del cierre}
.)Respuestas:
Parece que su código funciona, porque las conversiones de tipo implícito accidentalmente hacen lo correcto.
getchar()
devuelve unint
con un valor que se ajusta al rango deunsigned char
o esEOF
(que debe ser negativo, por lo general es -1). Tenga en cuenta que enEOF
sí mismo no es un carácter, sino una señal de que no hay más caracteres disponibles.Al almacenar el resultado desde
getchar()
adentroc
, hay dos posibilidades. El tipochar
puede representar el valor, en cuyo caso ese es el valor dec
. O el tipochar
no puede representar el valor. En ese caso, no está definido lo que sucederá. Los procesadores Intel simplemente cortan los bits altos que no encajan en el nuevo tipo (reduciendo efectivamente el valor del módulo 256char
), pero no debe confiar en eso.El siguiente paso es comparar
c
conEOF
. ComoEOF
es unint
,c
también se convertirá en unint
, conservando el valor almacenado enc
. Sic
pudiera almacenar el valor deEOF
, entonces la comparación tendrá éxito, pero si noc
puede almacenar el valor, entonces la comparación fallará, porque ha habido una pérdida irrecuperable de información al convertir a tipo .EOF
char
Parece que su compilador eligió
char
firmar el tipo y el valor de loEOF
suficientemente pequeño como para caberchar
. Sichar
no estuviera firmado (o si lo hubiera usadounsigned char
), su prueba habría fallado, porqueunsigned char
no puede contener el valor deEOF
.También tenga en cuenta que hay un segundo problema con su código. Como
EOF
no es un personaje en sí mismo, pero lo fuerza a unchar
tipo, es muy probable que haya un personaje que se malinterprete como siendoEOF
y para la mitad de los posibles personajes no está definido si se procesarán correctamente.fuente
char
valores fuera del rangoCHAR_MIN
...CHAR_MAX
será necesaria para generar un valor definido por la implementación, generar un patrón de bits que la implementación define como una representación de trampa o generar una señal definida por la implementación. En la mayoría de los casos, las implementaciones tendrían que pasar por mucho trabajo adicional para hacer algo más que la reducción del complemento a dos. Si la gente en el Comité de Normas se suscribieron a la idea de que los compiladores deben ser animados a poner en práctica comportamientos consistentes con la de la mayoría de los compiladores en ausencia de razones para hacer lo contrario ...(signed char)x
debería considerarse más claro y tan seguro como((unsigned char)x ^ CHAR_MAX+1))-(CHAR_MAX+1)
). Tal como es, no veo ninguna probabilidad de compiladores que implementan cualquier otro comportamiento que cumpla con el estándar actual; El único peligro sería que el estándar podría cambiarse para romper el comportamiento en el supuesto interés de "optimización".int i=129; signed char c=i;
es uno de esos comportamientos. Relativamente pocos procesadores tienen una instrucción quec
igualaríai
cuando está en el rango de -127 a +127 y produciría un mapeo consistente de otros valores dei
a valores en el rango de -128 a +127 que difieren de la reducción del complemento a dos, o. ..