C 编程/stdio.h/setvbuf
外观
setvbuf
是标准 C 中的一个函数,它允许程序员控制文件流的缓冲。它在 <stdio.h> 中声明;它的函数原型是
int setvbuf(FILE *stream, char *buf, int mode, size_t size);
stream 参数是指向文件流的指针,相关缓冲操作将在该文件流上执行;buf 是一个长度为 size 的字符数组,或者是一个空指针;mode 是所需的缓冲类型:_IOFBF
,表示全缓冲,_IOLBF
表示行缓冲,_IONBF
表示不缓冲。这三个宏定义在 <stdio.h> 中。setvbuf
在成功时返回零,在失败时返回非零值。
如果 buf 是空指针,系统将动态分配一个指定大小(size 个字符)的缓冲区。如果 mode 是 _IONBF
,则流 I/O 将不会被缓冲,导致流上的每个后续 I/O 操作都会立即执行,并且 buf 和 size 参数会被忽略。
一个相关的函数,setbuf
也控制文件流的缓冲。与 setvbuf
不同,setbuf
只接受两个参数。原型是
void setbuf(FILE *stream, char *buf);
setbuf
的行为等效于
(void)setvbuf(stream, buf, buf ? _IOFBF : _IONBF, BUFSIZ);
也就是说,如果 buf 不是 NULL
,则使用给定的缓冲区将流设置为全缓冲;否则,将流设置为不缓冲。如果向 setbuf
提供缓冲区,则缓冲区必须至少 BUFSIZ
字节长。该函数总是成功。
下面的代码非常不稳定,可能在特定的编译器上无法正常工作。它甚至可能导致缓冲区溢出.. C99 规定在写入流之后不能调用 setvbuf,因此此代码调用了未定义的行为。C99 脚注 230(非规范性)指出,应该在 main 结束时释放 buf 之前关闭流。
此程序的输出应该是 Hello world 后面跟着一个换行符。请注意,此示例是错误的,因为它实现了 manpage 清楚标记为错误的内容:缓冲区需要在流关闭时仍然存在。在这里,缓冲区在离开 main 时消失,但流仅在程序终止后关闭。
#include <stdio.h>
#include <stdlib.h>
int main(void) {
char buf[42];
if(setvbuf(stdout, buf, _IOFBF, sizeof buf)) {
perror("failed to change the buffer of stdout");
return EXIT_FAILURE;
}
printf("He");
/* The buffer contains "He"; nothing is written yet to stdout */
fflush(stdout); /* "He" is actually written to stdout */
if(setvbuf(stdout, NULL, _IONBF, 0)) {
perror("failed to change the buffer of stdout");
return EXIT_FAILURE;
}
printf("llo w"); /* "llo w" is written to stdout, there is no buffering */
if(setvbuf(stdout, buf, _IOLBF, sizeof buf)) {
perror("failed to change the buffer of stdout");
return EXIT_FAILURE;
}
printf("orld"); /* The buffer now contains "orld"; nothing is written yet to stdout */
putchar('\n'); /* stdout is line buffered; everything in the buffer is now written to stdout along with the newline */
return EXIT_SUCCESS;
}