问题描述
在 RTFM 之后,我现在有点不清楚如果返回值小于请求元素的数量,我可以从 fread()/fwrite() 的返回值中真正推断出什么。
先考虑
nhave = fread(dst,1,nwant,fp);
来自 C17 标准 (7.21.8.1/3):
fread 函数返回成功读取的元素数量,如果遇到读取错误或文件结尾,该数量可能小于 nwant。
因此,如果返回时 nhave 可能是读取错误或 eof(但也可能有其他原因)。由于它是 if 而不是 only if,因此在这种情况下不能得出 feof(fp)
if !ferror(fp)
。如果 !ferror(fp)
,根据标准,它仍然可以成功读取(nhave 字节)。
MSDN 和 cppreference.com 具有相同的措辞。
然后POSIX.1-2017:
成功完成后,fread() 将返回成功读取的元素数量,该数量小于 nwant 仅当遇到读取错误或文件结束时。
因此,如果返回时 nhave 一定 存在读取错误或 eof(不可能有其他原因)。因此,在这种情况下,可以得出 feof(fp)
if !ferror(fp)
。虽然与 C 标准中的规范不同,但这种行为并未被标记为 POSIX 中 C 标准的扩展。
来自 Linux(符合 POSIX 的平台)上的 fread(3) 手册页:
如果发生错误,或到达文件末尾,则返回值是一个短项目计数(或零)。
形式上,这是与 POSIX 的相反 (!) 语句。
现在考虑 fwrite(),
nhave = fwrite(src,fp);
让我们从这里的 POSIX.1-2017 开始:
fwrite() 函数应返回成功写入的元素数量,如果遇到写入错误,该数量可能小于 nwant。
因此,如果 nhave 可能(但不必)出现写入错误。在这种情况下,我们无法得出ferror(fp)
结论,但需要检查。
MSDN 和 cppreference.com 具有相同的措辞。
不过,根据 C17 标准(7.21.8.2/3),可以得出更多结论:
fwrite 函数返回成功写入的元素数量,只有在遇到写入错误时才会小于 nwant。
因此在这种情况下,nhave ferror(fp)。
这比上面的 fread() 更奇怪,因为 POSIX、Windows 和 C++ 都应该遵循 C 标准。
那么,这里发生了什么?只是措辞马虎?特别是从程序员的角度来看:
我可以假设 fread() 的返回值的 POSIX 措辞(如上所述)也适用于 C/C++/Windows/...,即, nhave
我是否可以假设 fwrite() 的返回值的 C 措辞(如上所述)也适用于 C++/Windows/POSIX/...,即 nhave
解决方法
那么,这里发生了什么?只是措辞马虎?
我认为您对单词的解析过于精细,如果您愿意,可以将其描述为规范的草率措辞。
首先考虑 fread()
。 C17 说,
fread
函数返回成功读取的元素数,
如果读取错误或文件结束,则可能小于 nmemb
遇到了。
我承认该措辞并未明确说明错误或文件结尾是读取的项目少于请求的项目的唯一原因,但如果这不是本意,那么为什么会出错和结尾-文件条件是否被提及?
fwrite
的 C17 措辞是明确的:
fwrite
函数返回成功写入的元素数,只有遇到写入错误时才会小于 nmemb。
比较两者,可以遵循两种不同的推理思路:
这两个函数应该是类似的,所以
fread
的歧义措辞应该被解释为与fwrite
明确指定的相同的“仅当”意义,OR-
如果本意是相同的解释,那么两者会使用相同的措辞。
我觉得第一个更有说服力,特别是考虑到它也解释了为什么 fread
文档甚至提到错误和文件结束条件。我完全准备接受尽管委员会的意图是最好的,但规范的语言并不完美。