11

Linux System Programming一书中,我读过这样的书:

fgetc将读取的字符作为unsigned char强制转换返回到文件或错误的结尾intEOF结尾。使用的一个常见错误fgetc是:

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

此代码的正确版本是:

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

那么,为什么我不能char在与比较之前将返回值转换为EOF?为什么我必须与EOF精确比较int?如EOF定义为-1,它通常不是转换为char吗?
是否存在不正确的平台/编译器?

4

2 回答 2

11

您不能将返回值转换为 char 因为返回值可能是EOF,并且EOFvalue 是系统相关的并且不等于任何有效的字符代码。关联

通常是这样,-1但你不应该假设。

c-faq-site检查这个很好的答案:

如果像上面的片段一样,将 getchar 的返回值分配给 char,则可能有两种失败模式。

  1. 如果类型 char 是有符号的,并且如果 EOF 被定义(通常)为 -1,那么十进制值为 255 的字符(C 中的“\377”或“\xff”)将被符号扩展并且比较等于EOF,过早终止输入。(假设 8 位字符)。

  2. 如果 char 类型是无符号的,实际的 EOF 值将被截断(通过丢弃其高位,可能导致 255 或 0xff)并且不会被识别为 EOF,从而导致有效的无限输入。

希望能帮助到你!

已编辑:(在此答案上添加了@FatalError 评论,这在 c-faq 网站上进行了解释,但这对我来说看起来更清楚)

“如果将其转换为 char,则 EOF 与某个有效字符具有相同的值,因此与该字符无法区分。仅此一项就足以证明不将结果设为 char”@FatalError 评论。

于 2012-06-15T19:49:36.917 回答
4

char在与 EOF 比较之前将值分配给 a 有两种可能性:

  • char是一个有符号的值。在这种情况下,有一个合法的字符(通常是 ÿ,带有分音符号的小拉丁字母 Y,U+00FF)将被误解为 EOF。
  • char是一个无符号值。在这种情况下,EOF 将被转换为 0xFF,然后将其提升int为正值,它永远不会与 EOF 进行比较,后者是负值。

无论哪种方式,该程序都会在某些时候出现异常。

存在(或更准确地说,曾经是)编译器错误的可能性,即分配正确发生但分配的值未用于比较。这将导致代码看起来可以正常工作,即使它不是。幸运的是,这不太可能是现代编译器中发现的问题。

于 2012-06-15T20:13:06.493 回答