printf是否总是在遇到换行符时刷新缓冲区?

时间:2011-03-08 06:23:38

标签: c posix

我的机器正在运行ubuntu 10.10,我正在使用标准的gnu C库。我的印象是,如果格式字符串中描述了换行符,printf会刷新缓冲区,但是下面的代码反复出现了这种趋势。有人可以澄清为什么缓冲区没有被刷新。

#include <stdio.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/wait.h>

int main()
{
    int rc;
    close(1);
    close(2);
    printf("HI 1\n");
    fprintf(stderr, "ERROR\n");

    open("newfile.txt", O_WRONLY | O_CREAT | O_TRUNC, 0600);
    printf("WHAT?\n");
    fprintf(stderr, "I SAID ERROR\n");

    rc = fork();

    if (rc == 0)
    {
        printf("SAY AGAIN?\n");
        fprintf(stderr, "ERROR ERROR\n");
    }
    else
    {
        wait(NULL);
    }

    printf("BYE\n");
    fprintf(stderr, "HI 2\n");

    return 0;
}

运行此程序后newfile.txt的内容如下:

HI 1
WHAT?
SAY AGAIN?
BYE
HI 1
WHAT?
BYE

3 个答案:

答案 0 :(得分:26)

不,标准表示如果可以确定输出设备是非交互设备,则stdout最初是完全缓冲的。

这意味着,如果您将stdout重定向到文件,它将不会在换行符上刷新。如果您想尝试强制它进行行缓冲,请使用setbufsetvbuf

C99的相关部分7.19.3 Files, paragraph 7声明:

  

在程序启动时,预定义了三个文本流,无需显式打开 - 标准输入(用于读取常规输入),标准输出(用于写入常规输出)和标准错误(用于写入诊断输出)。最初打开时,标准错误流未完全缓冲;当且仅当可以确定流不参考交互设备时,标准输入和标准输出流是完全缓冲的。

请记住第5.1.2.3/6部分:

  

交互设备的构成是实现定义的。

答案 1 :(得分:2)

如果输出设备是交互式,例如终端,则刷新

如果可以确定输出设备非交互式,例如文件,则必须flush输出缓冲区。新行不会自动执行此操作。

有关详细信息,请参阅paxdiablo's answer

答案 2 :(得分:0)

你有一种奇怪的幽默感。 :)

int main()
{
    int rc;
    close(1);
    close(2);
    printf("HI 1\n");
    fprintf(stderr, "ERROR\n");

关闭用于stdout和stderr的文件描述符,然后立即尝试使用C stdout和stderr FILE流。不是一个好主意,我不确定C库会向您报告错误,但崩溃将是一种可接受的可能性

除了奇怪之外,当您使用标准IO流功能进行写入时,缓冲部分取决于目标。如果您正在写一个终端,那么通常的行为就是线路缓冲。如果您正在写入管道,文件或套接字,那么通常的行为是块缓冲。您可以使用setvbuf(3)功能更改缓冲行为。有关缓冲行为的完整详细信息,请参见联机帮助页。