提问者:小点点

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


我的机器运行的是Ubuntu10.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个答案

匿名用户

不,标准规定,如果可以确定输出设备是非交互式的,那么stdout最初是完全缓冲的。

这意味着,如果将stdout重定向到文件,它将不会在换行时刷新。 如果要尝试并强制将其设置为行缓冲,请使用setbufsetvbuf

C99的相关部分7.19.3文件,第7段指出:

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

请记住5.1.2.3/6:

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

匿名用户

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

您必须刷新输出缓冲区,以防输出设备被确定为非交互设备(例如文件)。 新行不会自动执行此操作。

详见PaxDiablo的回答。

匿名用户

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

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

关闭用于stdout和stderr的文件描述符,然后立即尝试使用C stdout和stderr文件流。 这不是一个好主意,我不确定C库会做什么来向您报告错误 <罢工> 但坠机是一种可以接受的可能性 。

撇开这个奇怪的地方不谈,当您使用标准的IO流函数进行编写时,缓冲部分取决于目的地。 如果您正在向终端写入,那么通常的行为是行缓冲。 如果要写入管道,文件或套接字,那么通常的行为是块缓冲。 您可以使用setvbuf(3)函数更改缓冲行为。 缓冲行为的全部细节在手册页中。