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

问:我试图通过使用fopen模式"r+" ,读取某个string,写回修改后的string来更新文件,但不起作用。

答:请务必在写入之前调用fseek ,以便回溯到要覆盖的string的开头,并且因为在读/写“+”模式下读写之间始终需要fseekfflush

我的问题是为什么 fseekfflush总是需要在读/写“+”模式读写之间? Andrew Koenig的“ C陷阱和陷阱” (1989)第5.2节提到,这是因为向后兼容性问题。 任何人都可以详细解释?

该库缓冲input和输出操作。 查看setvbuf()和_IOFBF,_IOLBF参数。 fseek()或fflush() 要求库提交缓冲操作。 该标准指定一个search或刷新操作是强制性的,以允许图书馆的一些捷径; 否则,对于每个I / O操作,lib将不得不检查前面的操作是否也是读操作(或写操作),并且如果I / O的“方向”改变,则自己触发刷新。

因为它使OS /库代码更简单。 文件stream可能有不同的读取写入缓冲区,并且需要额外的努力来确保它们始终同步。 在不需要的时候,这将会降低性能。

相反,程序员需要在需要时明确地做到这一点。

请阅读Plauger的“ 标准C库 ”,了解为什么(C89)标准库的各种function保持原样(特别是为什么标准I / O库的某些部分保持原样)。 其中一个原因是,C运行在非常多元化的系统和不同的媒体上, 诸如磁带之类的设备可能需要处理与您习惯考虑的磁盘驱动器稍微不同的处理。 而且,在Unix上,考虑你的“tty”设备 – 它将键盘和鼠标连接到一个屏幕 – 三个完全不同的硬件。 这些之间的协调是非常棘手的。 标准中的规则使得它更容易。


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

§7.21.5.3fopen函数

¶7以更新模式打开文件(上述模式参数值列表中的第二个或第三个字符为“+”)时,可以在关联的stream上执行input和输出。 然而,输出不应该直接跟随input,而不需要中间调用fflush函数或文件定位函数( fseekfsetposrewind ),并且input不应该直接跟随输出,而不需要中间调用文件定位函数,除非input操作遇到文件结束。 在某些实现中打开(或创build)具有更新模式的文本文件可能会打开(或创build)二进制stream。