使用fgetc
读取流的下一个字符时,通常会检查
if ((c = fgetc (stream)) != EOF)
其中c
属于int
类型。然后,文件结束已经达到并且条件将失败,或者c
应该是转换为unsigned
的{{1}}字符,预计与int
不同1}} -for EOF
被确定为否定。很好......显然。
但是存在一个小问题...通常EOF
类型不超过8位,而char
必须至少有16位,因此每个int
都可以表示作为unsigned char
。然而,在int
将有16或32位的情况下(我知道,实际上情况从未如此......),没有理由为什么不能有char
,所以它(理论上!)可能sizeof(int) == 1
返回fgetc (stream)
(或另一个负值),但文件结尾尚未达到......
我错了吗?如果未达到文件结尾,C标准中是否会阻止EOF
返回fgetc
? (如果是的话,我找不到它!)。或EOF
语法不完全可移植?...
编辑:的确,这是问题#3860943的重复。我在第一次搜索时没有找到这个问题。谢谢您帮忙! : - )
答案 0 :(得分:2)
如果您正在读取仅标准ASCII的流,那么在真正的文件结束之前没有接收相当于EOF的字符的风险,因为有效的ASCII字符代码最多只能达到127。但是读取二进制文件时可能会发生这种情况。该字节需要为255(无符号)以对应-1签名字符,并且没有任何东西阻止它出现在二进制文件中。
但是关于你的具体问题(如果标准中有什么内容),不完全是......但请注意fgetc将字符作为无符号字符提升,因此它不会对此产生负面影响无论如何。唯一的风险是,如果您明确或隐式地将返回值转换为signed char(例如,如果您的c变量是signed char)。
注意:正如@Ulfalizer在评论中提到的那样,在一个罕见的情况下,您可能需要担心:如果sizeof(int)== 1,并且您正在读取包含非文件的文件-ascii字符,那么你可能得到一个不是真正的EOF的-1返回值。请注意,发生这种情况的环境非常罕见(据我所知,低端8位微控制器的编译器,如8051)。在这种情况下,安全选项是将feof()测试为@pmg建议。
答案 1 :(得分:2)
你问:
如果未达到文件结尾,C标准中是否会阻止
fgetc
返回EOF
?
相反,标准明确允许在发生错误时返回EOF
。
如果发生读取错误,则设置流的错误指示符,
fgetc
函数返回EOF
。
在脚注中,我看到了:
使用
feof
和ferror
函数可以区分文件结束和读取错误。
您还问:
或
if ((c = fgetc (stream)) != EOF)
语法不完全可移植?
在CHAR_BIT
大于8且sizeof(int) == 1
的理论平台上,这不是检查已达到文件结尾的有效方法。为此,您必须诉诸feof
和ferror
。
c = fgetc (stream);
if ( !feof(stream) && !ferror(stream) )
{
// Got valid input in c.
}
答案 2 :(得分:1)
我同意你的阅读。
C标准说(C11,7.21.7.1 fgetc函数p3):
如果设置了流的文件结束指示符,或者流位于文件结尾,则设置流的endof-file指示符并且fgetc函数返回EOF。否则,fgetc函数返回stream指向的输入流中的下一个字符。如果发生读取错误,则设置流的错误指示符和fgetc函数 返回EOF。
标准中没有任何内容(假设UCHAR_MAX > INT_MAX
)不允许托管实现中的fgetc
返回等于EOF
的值,该值既不是文件结尾也不是错误状态指示器。