fgetc, проверка EOF

в книге Системное Программирование Linux я читал такие:

fgetc возвращает символ, считываемый как unsigned char преобразован в int или EOF в конце файла или ошибки. Распространенная ошибка с использованием fgetc - это:

char c;
if ((c = fgetc()) != EOF) {...}

правильная версия этого кода:

int c;
if ((c = fgetc()) != EOF) { printf("%c", (char)c); ... }

Итак, почему я не могу привести возвращаемое значение к char перед сравнением с EOF? Почему я должен сравнивать EOF именно с int? As EOF определяется как -1, разве он обычно не отлит в char?
существуют ли платформы/компиляторы, где это не так?

2 ответов


вы не можете привести возвращаемое значение в char, потому что возвращаемое значение может быть EOF и EOF значение зависит от системы и не равно любому допустимому символьному коду. ссылке

обычно -1 но вы не должны предполагать, что.

проверьте этот отличный ответ от C-faq-сайт:

возможны два режима отказа, если, как в приведенном выше фрагменте, getchar возвращаемое значение присваивается литер.

  1. Если тип char подписан, и если EOF определен (как обычно) как -1, символ с десятичным значением 255 ('\377' или '\xff' в C) будет знак-расширен и будет сравниваться равным EOF, преждевременно прекращая вход. (если 8 бит тип char).

  2. Если тип char без знака, фактическое значение EOF будет усечено (по имея отброшенные биты более высокого порядка, возможно, в результате 255 или 0xff) и не будет распознан как EOF, в результате эффективно бесконечный вход.

надеюсь, что это помогает!

редактировать: (добавлен комментарий @FatalError к этому ответу, это объясняется на сайте c-faq, но мне это кажется более ясным)

" Если вы бросаете его в char, тогда EOF принимает то же значение, что и некоторый действительный символ, и, следовательно, становится неотличимым от этого символа. Одного этого должно быть достаточно, чтобы не сделать результат char" @ FatalError комментарий.


есть две возможности, когда вы присвоить значение char перед сравнением с EOF:

  • char - знаковое значение. В этом случае есть законный характер (часто ÿ, маленькая латинская буква Y с DIAERESIS, U+00FF), который будет неправильно истолкован как EOF.
  • char - значение без знака. В этом случае EOF будет переведен в 0xFF, а затем повышен до int как положительное значение, которое никогда не сравнится равным EOF которое a отрицательное значение.

в любом случае, программа будет плохо себя вести некоторое время.

существует (или, точнее, раньше была) вероятность ошибки компилятора, так что назначение произошло правильно, но назначенное значение не было использовано для сравнения. Это приведет к тому, что код будет работать нормально, даже если это не так. К счастью, это вряд ли будет проблемой в современном компиляторе.