Eu li no livro The C Programming Language de Dennis Ritchie, que int
deve ser usado para uma variável conter EOF - para torná-la suficientemente grande para que possa manter o valor EOF - não char
. Mas o código a seguir funciona bem:
#include<stdio.h>
main() {
char c;
c=getchar();
while(c!=EOF) {
putchar(c);
c=getchar();
}
}
Quando não houver mais entrada, getchar
retorna EOF. E no programa acima, a variável c
, com o tipo char, é capaz de segurá-la com sucesso.
Por que isso funciona? Conforme a explicação no livro acima mencionado, o código não deve funcionar.
0xff
. Armazenar o resultado degetchar()
em umint
resolve esse problema. Sua pergunta é essencialmente a mesma que a pergunta 12.1 na FAQ do comp.lang.c , que é um excelente recurso. (Além disso,main()
deve serint main(void)
, e não faria mal para adicionar umreturn 0;
antes do fechamento}
.)Respostas:
Seu código parece funcionar, porque acidentalmente as conversões implícitas de tipo fazem a coisa certa.
getchar()
retorna umint
com um valor que se ajusta ao intervalo deunsigned char
ou éEOF
(que deve ser negativo, geralmente é -1). Observe queEOF
ele próprio não é um personagem, mas um sinal de que não há mais caracteres disponíveis.Ao armazenar o resultado de
getchar()
dentroc
, há duas possibilidades. O tipochar
pode representar o valor; nesse caso, esse é o valor dec
. Ou o tipochar
não pode representar o valor. Nesse caso, não está definido o que acontecerá. Os processadores Intel apenas cortam os bits altos que não se encaixam no novo tipo (reduzindo efetivamente o módulo de valor 256 parachar
), mas você não deve confiar nisso.O próximo passo é comparar
c
comEOF
. ComoEOF
é umint
,c
também será convertido em umint
, preservando o valor armazenado emc
. Sec
puder armazenar o valor deEOF
, a comparação será bem-sucedida, mas se nãoc
puder armazenar o valor, a comparação falhará, porque houve uma perda irrecuperável de informações durante a conversão para o tipo .EOF
char
Parece que seu compilador escolheu fazer com que o
char
tipo seja assinado e o valorEOF
pequeno o suficiente para caberchar
. Sechar
não tivesse assinado (ou se você tivesse usadounsigned char
), seu teste teria falhado, porqueunsigned char
não pode conter o valor deEOF
.Observe também que há um segundo problema com o seu código. Como
EOF
não é um personagem em si, mas você o força a umchar
tipo, é muito provável que exista um personagem que seja mal interpretado como sendoEOF
e, para metade dos caracteres possíveis, é indefinido se eles serão processados corretamente.fonte
char
valores fora da faixaCHAR_MIN
..CHAR_MAX
will é necessária para gerar um valor definido pela implementação, gerar um padrão de bits que a implementação define como uma representação de interceptação ou gerar um sinal definido pela implementação. Na maioria dos casos, as implementações teriam que passar por muito trabalho extra para fazer algo diferente da redução do complemento de dois. Se as pessoas no Comité de Normas subscreveu a ideia de que os compiladores devem ser encorajados a implementar comportamentos consistentes com a da maioria dos outros compiladores, na ausência de razões para fazer o contrário ...(signed char)x
deve ser considerado mais claro e tão seguro quanto((unsigned char)x ^ CHAR_MAX+1))-(CHAR_MAX+1)
.) Como é, não vejo nenhuma probabilidade de compiladores implementando qualquer outro comportamento em conformidade com o padrão atual; o único perigo seria que o Padrão pudesse ser alterado para interromper o comportamento no suposto interesse de "otimização".int i=129; signed char c=i;
é um desses comportamentos. Relativamente poucos processadores têm uma instrução que seriac
iguali
quando está no intervalo -127 a +127 e produziria qualquer mapeamento consistente de outros valores dei
para valores no intervalo -128 a +127 que diferiam da redução do complemento de dois ou. ..