Stderr和Stdout在C?

时间:2013-11-14 23:29:13

标签: c stream stdout stderr

我正在编写一个小程序,它根据不同的事件有各种控制台输出字符串。当我查找发送这些消息的最佳方式时,我遇到了一些有点令人困惑的事情。

我已经读过stderr用于直接向控制台发送消息 - not buffered。相反,我读到stdoutbuffered,并且通常用于将消息重定向到各种streams?,可能是也可能不是错误消息,输出文件或其他介质。

当某些东西被称为缓冲而不是缓冲时有什么区别?当我读到消息是直接射到输出并且缓冲时,这是有道理的。但同时我意识到我并不完全确定缓冲是什么意思。

4 个答案:

答案 0 :(得分:3)

通常,stdout是行缓冲的,这意味着发送到stdout的字符“堆叠”直到换行符到达,此时全部输出。

答案 1 :(得分:2)

缓冲流是指在一定阈值之前继续写入的流。此阈值可以是特定字符,如Konrad提到的行缓冲,或其他阈值,例如写入的特定字符数。

缓冲旨在加快输入/输出操作。计算机执行的最慢的事情之一是写入流(无论是控制台还是文件)。当不需要立即看到东西时,它可以节省一段时间来存储它。

您是对的,stderr通常是无缓冲的流,而stdout通常是缓冲的。因此,有时您可以将内容输出到stdou,然后输出到stderr,并且stderr首先出现在控制台上。如果您想使stdout行为相似,则每次写入后都必须flush

答案 2 :(得分:2)

当缓冲输出流时,这意味着当您告诉它时,流不一定输出数据。每个IO操作可能会产生大量开销,因此大量的小IO操作可能会造成瓶颈。通过缓冲IO操作然后立即刷新多个操作,可以减少这种开销。

虽然stdoutstderr在缓冲方面可能表现不同,但这通常不是它们之间的决定因素,不应该依赖。如果您绝对需要立即输出,请始终手动flush流。

答案 3 :(得分:1)

假设

int main(void)
{
    printf("foo\n");
    sleep(10);
    printf("bar\n");
}

在控制台上执行时

$ ./a.out

您将看到foo行,10秒后bar行( - >行缓冲)。将输出重定向到文件或管道时

$ ./a.out > /tmp/file

文件保持为空( - >缓冲),直到程序终止( - >退出时隐式fflush())。

如果上面的行不包含\n,则在程序终止之前,您不会在控制台上看到任何内容。

在内部,printf()将一个字符添加到缓冲区。为了让事情变得更轻松,让我来描述一下fputs(char const *s, FILE *f)而不是。 FILE可能被定义为

struct FILE {
    int fd;   /* is 0 for stdin, 1 for stdout, 2 for stderr (usually) */
    enum buffer_mode mode;
    char buf[4096];
    size_t count; /* number of chars in buf[] */
};
typedef struct FILE *FILE;

int fflush(FILE *f)
{
    write(f->fd, f->buf, f->count);
    f->count = 0;
}

int fputc(int c, FILE *f)
{
    if (f->count >= ARRAY_SIZE(f->buf))
        fflush(f);
    f->buf[f->count++] = c;
} 

int fputs(char const *s, FILE *f)
{
    while (*s) {
        char c = *s++;

        fputc(c, f);

        if (f->mode == LINE_BUFFERED && c == '\n')
            fflush(f);
    }

    if (f->mode == UNBUFFERED)
        fflush(f);
}