为什么在更新模式下读写之间总是需要fseek或fflush?

pie*_*fou 13 c file-io fseek

问:我正在尝试通过使用fopen模式"r+",读取某个字符串以及写回修改后的字符串来更新文件,但它无法正常工作.

答:一定要叫fseek你写之前,既要寻求回到你想覆盖字符串的开头,并且因为一个fseekfflush总是阅读,并在阅读写作之间需要/写"+"模式.

我的问题是在读/写"+"模式下读写之间为什么 fseekfflush总是需要?Andrew Koenig的C Traps and Pitfalls(1989)第5.2节 提到它是由于向后兼容性问题.谁能详细解释一下?

Dev*_*lar 15

该库缓冲输入和输出操作.检查setvbuf()和_IOFBF,_IOLBF参数到该funktion.fseek()或fflush()要求库提交缓冲操作.该标准将搜索或刷新操作指定为强制性,以使库具有一些快捷方式; 否则,对于每个I/O操作,lib必须检查先前的操作是否也是读操作(或写操作),并且如果I/O的"方向"改变则自动触发刷新.


Art*_*ius 5

因为它使OS /库代码更简单.文件流可能具有单独的读取写入缓冲区,并且需要额外的努力来确保它们始终是同步的.如果不需要,这会花费性能.

因此,程序员需要在需要时明确地执行此操作.


Jon*_*ler 5

阅读Plauger的“ 标准C库 ”,以了解为什么(C89)标准库的各种功能保持不变,尤其是为什么标准I / O库的各个部分保持不变。原因之一是C在非常不同的系统和不同的媒体上运行;诸如磁带之类的设备可能需要与您惯常想到的磁盘驱动器有所不同。另外,在Unix上,考虑您的“ tty”设备-它将键盘和鼠标连接到屏幕-硬件的三个完全不同。两者之间的协调足够棘手。该标准中的规则使其变得更容易。


请注意,该标准规定了这一点。这来自C11标准ISO / IEC 9899:2011,但在以前的版本中的措辞相似:

§7.21.5.3 fopen功能

¶7当使用更新模式打开文件时(上面的模式参数值列表中的第二个或第三个字符'+'),可以在关联的流上执行输入和输出。然而,输出不应直接跟随输入而没有插入调用fflush功能或文件定位功能(fseekfsetpos,或rewind),并且输入不应直接跟随输出而没有中间呼叫到一个文件中的定位功能,除非输入操作遇到文件结尾。在某些实现中,以更新模式打开(或创建)文本文件可能会打开(或创建)二进制流。