fgetc,检查EOF

ppr*_*ger 10 c eof fgetc

Linux系统编程一书中,我读过这样的文章:

fgetc返回读取作为字符unsigned char强制转换为intEOF在文件或错误的结束.使用的常见错误fgetc是:

char c;
if ((c = fgetc()) != EOF) {...}
Run Code Online (Sandbox Code Playgroud)

这段代码的正确版本是:

int c;
if ((c = fgetc()) != EOF) { printf("%c", (char)c); ... }
Run Code Online (Sandbox Code Playgroud)

那么,为什么我不能char在比较之前投出一个返回值EOF呢?为什么我要与之EOF完全比较int?如EOF定义的那样-1,它通常不会被投放到char
是否有平台/编译器不适用?

Cac*_*nta 10

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

通常它是,-1但你不应该假设.

c-faq网站上查看这个很棒的答案:

如果在上面的片段中,getchar的返回值被赋值给char,则可能出现两种失败模式.

  1. 如果char类型被签名,并且如果EOF被定义为(通常)为-1,则带有十进制值255(C中的'\ _377'或'\ xff')的字符将被符号扩展并将比较等于EOF,过早地终止输入.(假设8位字符).

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

希望能帮助到你!

编辑:(在这个答案上添加@FatalError评论,这在c-faq网站上有解释,但这对我来说更清楚)

"如果你将它转换为char,那么EOF与某个有效字符的值相同,因此与该字符无法区分.仅此一点就足以证明不能使结果成为字符"@FatalError注释.

  • 如果将它强制转换为`char`,那么`EOF`与某个有效字符的值相同,因此与该字符无法区分.仅这一点就足以证明不能使结果成为"char". (3认同)

Jon*_*ler 5

将值分配给 a 时有两种可能性char

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

不管怎样,程序有时会出现错误。

\n\n

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

\n