使用带文件的fseek(文件,0,SEEK_END)了解二进制流的未定义行为

C规范有一个有趣的脚注(#268C11dr§7.21.39)

“将文件位置指示器设置为文件结尾,与fseek(file, 0, SEEK_END) ,具有二进制流的未定义行为(因为可能是尾随空字符)或具有状态相关编码的任何流不能确定在最初的轮class状态结束。“

这是否适用于读取文件的二进制流? (从物理设备)

IMO,磁盘上的二进制文件只是一个字节的海洋。 在我看来,二进制文件不能具有状态相关的编码,因为它是一个二进制文件。 我对“二进制广泛流”的概念很模糊,如果它甚至可以应用于磁盘I / O.

我看到在串口流上调用fseek(file, 0, SEEK_END)就像一个com端口或stdin可能无法达到真正的结束,因为还没有确定结束 。 从而将问题缩小到物理文件。


[编辑]答案:与老年人(可能直到20世纪80年代后期)的关注。 目前在2014年,Windows,POSIT特定和非异国他人:不是问题。

@Shafik Yaghmour提供了一个很好的参考, 使用fseek和ftell来确定文件的大小是否有漏洞? 。 @Jerry Coffin将CP / M视为二进制文件并不总是具有精确的长度。 (每个wiki 128字节的记录)。

感谢@Keith Thompson的回答。

这一点解释了规范的“(因为可能有尾随空字符)”评论。

在您可能使用的任何系统上,二进制文件将是具有精确指定大小的8位字节序列。 但并非所有系统都以这种方式存储文件,并且C标准经过精心设计,可以移植到具有不寻常特性的系统。

例如,符合C的实现可以在操作系统上运行,该操作系统将文件存储为512字节块的序列,而不指示最终块的多少字节是重要的。 在这样的系统上,当创建二进制文件时,OS可能用零字节填充最后一个块的剩余部分。 当您从这样的文件中读取时,填充字节可能出现在输入中(即使它们从未显式写入文件),也可能被忽略(即使创建该文件的程序可能已明确写入) 。

如果您正在从不可搜索的流中读取(例如键盘输入),那么fseek(file, 0, SEEK_END)将不会仅仅给您一个错误的结果,它将通过返回非零结果来指示失败。 (在POSIX兼容系统上,它返回-1并设置errno ; ISO C不需要它。)

在大多数系统上,二进制文件上的fseek(file, 0, SEEK_END)将寻找文件的实际末尾(由确切地写入文件的字节数确定的位置),或返回明确的失败指示。 如果你正在使用POSIX特定的function,你可以安全地假设这种行为; 您可以对Windows和许多其他系统做出相同的假设。 如果您希望您的代码100%可移植到异国情调的系统,您不应该假设二进制文件不会被额外的零字节填充。