跳转到内容

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 操作都会立即执行,并且 bufsize 参数会被忽略。

一个相关的函数,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;
}
[编辑 | 编辑源代码]
华夏公益教科书