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

chu*_*ica 12 c binary file-io fseek

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

"将文件位置指示器设置为文件结尾,如同fseek(file, 0, SEEK_END),具有二进制流的未定义行为(因为可能存在尾随空字符)或具有状态相关编码但未确定以初始移位状态结束的任何流".

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

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

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


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

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

感谢@Keith Thompson的回答.

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

Kei*_*son 7

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

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

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

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

  • @chux:不,但我不熟悉当前的所有文件系统。(可能有一些适用于嵌入式系统的东西。) (2认同)
  • “在您可能使用的任何系统上,将是......精确指定的大小”,我已经_使用_很多文件系统,甚至是类似 CP/M 的操作系统,称为 CBM DOS,我相信它也缺少字节具体文件大小。不过,我怀疑我很快就会为该平台编写 C 代码。我认为奇怪的 C 规范是关于新的东西,而不是关于旧的东西。谢谢。 (2认同)