C语言-文件输入/输出缓冲区和setvbuf()函数

7
在C语言中,fopen()函数是否真的会创建两个缓冲区,一个用于输入,另一个用于输出?
这是我的C语言书籍上所说的:
通常,使用标准I/O的第一步是使用fopen()打开文件。(不过要注意,stdin、stdout和stderr文件会自动打开。)fopen()函数不仅会打开文件,还会设置一个缓冲区(在读写模式下有两个缓冲区),并设置一个包含有关该文件数据的数据结构...
如果使用fopen()打开文件会创建两个缓冲区,在类似于"a+"的读写模式下,即既可以读取也可以写入...
FILE * fp = fopen ("file.txt", "a +");
setvbuf (destination_file, NULL, _IOFBF, BUFFER_SIZE);

setvbuf() 函数所指的缓冲区是什么?


1
当书中说“两个缓冲区”时,它是在胡说八道。实际上只使用了一个缓冲区。 - Jonathan Leffler
2个回答

4
一个打开的文件只有一个缓冲区,无论是为读取、写入还是两者都打开。
《C标准》第7.21.5.3节详细介绍了fopen函数,其中规定:
当以更新模式(在上述模式参数值列表中作为第二个或第三个字符的+)打开文件时,可对关联流执行输入和输出。但不能直接在输出后紧跟输入,除非在它们之间调用fflush函数或文件定位函数(fseekfsetposrewind),也不能在输入后紧跟输出,除非输入操作遇到文件结束。在某些实现中,以更新模式(或创建)文本文件可能会改为打开(或创建)二进制流。
上面的段落说明在执行输入(无论是显式还是通过定位函数隐式执行)之前必须刷新输出缓冲区,以及在执行输出之后执行输入时也是如此。这是仅有单个缓冲区的结果。
从逻辑角度来看,这也是有意义的,因为它防止读取和写入对文件内容产生不一致的视图。

3

setvbuf()函数所涉及到的缓冲区是指"两者"。调用fopen()不一定会为读写模式创建 "两个缓冲区",大多数实现只使用一个缓冲区,因为这就足够了。

C标准 隐含地支持单个缓冲区。根据7.21.5.3 fopen函数, 第7段

当使用更新模式(上述模式参数值列表中第二个或第三个字符为 '+')打开文件时,关联流可以进行输入和输出。但是,在没有调用 fflush 函数或文件定位函数(fseek, fsetposrewind) 的情况下,不能直接在输出之后进行输入;在没有调用文件定位函数的情况下,不能直接在输入之后进行输出,除非输入操作遇到了文件结束。在某些实现中,使用更新模式打开(或创建)文本文件可能会改为打开(或创建)二进制流。

该段落的要求允许使用单个缓冲区。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接