繁体   English   中英

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

[英]Does printf always flush the buffer on encountering a newline?

我的机器运行的是 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

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

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

C99 的相关部分, 7.19.3 Files, paragraph 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 FILE 流。 这不是一个好主意,我不确定 C 库将如何向您报告错误, 但崩溃将是一种可以接受的可能性

撇开这个奇怪,当您使用标准 IO 流函数进行写入时,缓冲部分取决于目标。 如果您正在写入终端,那么通常的行为是行缓冲。 如果您正在写入管道、文件或套接字,则通常的行为是块缓冲。 您可以使用setvbuf(3)函数更改缓冲行为。 缓冲行为的完整详细信息在联机帮助页中。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM