Skip to content
Tiantan
Articles

Armazenando o caractere EOF (Fim do Arquivo) em um tipo de char

On Fevereiro 18, 2021 by admin

Eu li na Linguagem de Programação C de Dennis Ritchie livro que int deve ser usado para uma variável para conter EOF – para torná-lo suficientemente grande para que possa conter 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 houver não é mais entrada, getchar retorna EOF. E no programa acima, a variável c, com tipo char, é capaz de mantê-lo com sucesso.

Por que isso funciona? De acordo com a explicação no livro mencionado acima, o código não deve funcionar.

Comentários

  • Não há nenhum caractere EOF.
  • Este código provavelmente falhará se você ler um caractere com o valor 0xff. Armazenando o resultado de getchar() em um int resolve esse problema. Sua pergunta é essencialmente igual à pergunta 12.1 no FAQ do comp.lang.c , que é um excelente recurso. (Além disso, main() deve ser int main(void), e não ' custaria adicionar um return 0; antes do fechamento }.)
  • @delnan: O artigo vinculado não é ' Não estou certo sobre como o Unix trata o control-D. Ele não ' fecha o fluxo de entrada; simplesmente faz com que qualquer fread () que está bloqueando o console retorne imediatamente com quaisquer dados ainda não lidos. Muitos programas interpretam um retorno de zero byte de fread () como indicando EOF, mas o arquivo na verdade permanecerá aberto e será capaz de fornecer mais entradas.

Resposta

Seu código parece funcionar, porque as conversões de tipo implícitas acidentalmente acontecem para fazer a coisa certa.

getchar() retorna um int com um valor que se encaixa no intervalo de unsigned char ou é EOF ( que deve ser negativo, geralmente é -1). Observe que EOF em si não é um caractere, mas um sinal de que não há mais caracteres disponíveis.

Ao armazenar o resultado de getchar() em c, existem duas possibilidades. O tipo char pode representar o valor, caso em que é o valor de c. Ou o tipo char 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 cabem no novo tipo (reduzindo efetivamente o valor do módulo 256 para char), mas você não deve confiar nisso.

A próxima etapa é comparar c com EOF. Como EOF é um int, c será convertido em int também, preservando o valor armazenado em c. Se c puder armazenar o valor de EOF, a comparação será bem-sucedida , mas se c puder não armazenar o valor, a comparação falhará, porque houve uma perda irrecuperável de informações durante a conversão EOF para digitar char.

Parece que seu compilador escolheu fazer o tipo char assinado e o valor de EOF pequeno o suficiente para caber em char. Se char não tivesse sinal (ou se você tivesse usado unsigned char), seu teste teria falhado, porque unsigned char não pode “manter o valor de EOF.


Observe também que há um segundo problema com seu código. Como EOF não é um caractere em si, mas você o força em um tipo char, é muito provável que haja um caractere por aí que é mal interpretado como sendo EOF e para metade dos caracteres possíveis é indefinido se eles serão processados corretamente.

Comentários

  • Coerção para digitar char valores fora do intervalo CHAR_MIN .. CHAR_MAX vontade é necessária para produzir um valor Definido pela Implementação, produz um padrão de bits que a implementação define como uma representação de trap, ou levanta um sinal definido pela implementação. Na maioria dos casos, as implementações teriam que passe por muito trabalho extra para fazer qualquer coisa além de duas ' redução do complemento de s.Se as pessoas no Comitê de Padrões subscrevessem a ideia de que os compiladores deveriam ser encorajados a implementar comportamentos consistentes com os da maioria dos outros compiladores na ausência de razões para fazer o contrário …
  • … Eu consideraria isso coerção como sendo confiável (para não dizer que o código não deve ' documentar suas intenções, mas que (signed char)x deve ser considerado mais claro e seguro como ((unsigned char)x ^ CHAR_MAX+1))-(CHAR_MAX+1).) Do jeito que está, eu não ' não vejo qualquer probabilidade de compiladores implementarem qualquer outro comportamento compatível com ' s padrão; o único perigo seria que o Padrão pudesse ser alterado para quebrar o comportamento no suposto interesse de " otimização ".
  • @supercat: o padrão é escrito de forma que nenhum compilador precise produzir código que tenha um comportamento que não seja suportado naturalmente pelo processador ao qual se destina. A maior parte do comportamento indefinido ocorre porque (no momento da redação do padrão) nem todos os processadores se comportavam de maneira consistente. Com os compiladores ficando mais maduros, os escritores de compiladores começaram a tirar vantagem do comportamento indefinido para fazer otimizações mais agressivas.
  • Historicamente, a intenção do Padrão era principalmente como você descreve, embora o Padrão descreva alguns comportamentos em detalhes suficientes para exigir que os compiladores de algumas plataformas comuns gerem mais código do que seria necessário em uma especificação mais flexível. A coerção de tipo em int i=129; signed char c=i; é um desses comportamentos. Relativamente poucos processadores têm uma instrução que tornaria c igual i quando ' s em o intervalo de -127 a +127 e produziria qualquer mapeamento consistente de outros valores de i para valores no intervalo de -128 a +127 que diferiam de dois ' redução do complemento de s, ou …
  • … levantaria consistentemente um sinal em tais casos. Uma vez que o Padrão requer que as implementações produzam um mapeamento consistente ou levantem um sinal de forma consistente, as únicas plataformas onde o Padrão deixaria espaço para algo diferente de dois ' redução do complemento s seriam coisas como DSPs com hardware de saturação aritmética. Quanto à base histórica para comportamento indefinido, eu diria que o problema não é ' apenas com plataformas de hardware. Mesmo em uma plataforma onde o overflow se comportaria de uma maneira muito consistente, pode ser útil ter um compilador para interceptá-lo …

Written by admin

Deixe uma resposta Cancelar resposta

O seu endereço de email não será publicado. Campos obrigatórios marcados com *

Artigos recentes

  • Usando um balun com um dipolo ressonante
  • Qual é a diferença entre “ cant ” e “ cant ”? [duplicar]
  • No JFK, você pode se mover entre os terminais do lado ar em voos domésticos?
  • “ Muito apreciada ” ou “ muito apreciada ”
  • O que ' ideias abstratas ' significa? [fechado]

Arquivo

  • Fevereiro 2021
  • Janeiro 2021
  • Dezembro 2020
  • Novembro 2020
  • Deutsch
  • Nederlands
  • Svenska
  • Norsk
  • Dansk
  • Español
  • Français
  • Português
  • Italiano
  • Română
  • Polski
  • Čeština
  • Magyar
  • Suomi
  • 日本語
  • 한국어

Copyright Tiantan 2021 | Theme by Theme in Progress | Proudly powered by WordPress

Back to top