3

我知道这是因为 stdout 的缓冲,但是我什么时候可以在下面的程序中期望 stdout 的输出。如果我运行,我总是得到“stderr”作为输出。如果我添加 '\n' 或 fflush(stdout) 那么只有我得到两个语句。如果我不添加 '\n' 或 fflush(stdout),我不会得到“stdout”作为输出。如果我不添加 '\n' 或 fflush(stdout),我什么时候会得到所有缓冲的“stdout”作为输出。

#include <stdio.h>
#include <unistd.h>
int main()
{
      for(;;)
      {
              fprintf(stdout,"stdout");
              fprintf(stderr,"stderr");
              sleep(1);
      }
      return 0;
} 
4

3 回答 3

4

实际上,新行或刷新是因为默认情况下stdout在引用终端设备时会缓冲行。

更准确地说:标准输入和标准输出是完全缓冲的,当且仅当它们不引用交互式设备时。标准错误永远不会完全缓冲。

关于行缓冲,引用APUE

行缓冲有两个注意事项。首先,标准 I/O 库用于收集每一行的缓冲区大小是固定的,因此如果我们在写入换行符之前填充此缓冲区,则可能会发生 I/O。其次,每当通过标准 I/O 库从 (a) 无缓冲流或 (b) 行缓冲流(需要从内核请求数据)请求输入时,所有行缓冲输出流都会被刷新。(b) 上的限定符的原因是请求的数据可能已经在缓冲区中,这不需要从内核读取数据。显然,来自无缓冲流的任何输入(项目 (a))都需要从内核获取数据。

要将其更改为无缓冲,请使用setvbuf

setvbuf(stdout, NULL, _IONBF, 0);
于 2013-07-15T15:32:18.897 回答
0

发送到 stderr 的输出通常会立即打印。它是标准错误输出。当然,错误应该立即显示,因此任何存在的缓冲区都会立即刷新。

另一方面,标准输出是缓冲的。打印出该缓冲区因语言而异,但通常至少需要以下两项中的一项:/n或其他类型的换行符,或.flush();. 如果您不提供这些选项,那么通常您必须等待缓冲区填满。这可能需要任何时间,因为它几乎完全取决于缓冲区的大小。

按照惯例,处理流的方式是您将尽可能多的信息塞入其中,然后调用.flush(). 如果缓冲区恰好在此期间填满,那么数据将被发送到它要去的任何地方,并且缓冲区再次开始填满。

但是,在这里,您正在填充一个接收文本的缓冲区。与二进制信息相比,文本并没有真正占用大量空间(这是一个非常主观的陈述,应该松散地解释),因此填充缓冲区可能需要相当长的时间。

stdout最好的做法是,一旦您“输入”了您想要打印的所有文本,您就可以手动刷新流 ( )。

于 2013-07-15T15:36:06.703 回答
0

fprintf默认是行缓冲的。您可以通过调用setvbuf来更改行为。它允许您将其设置为“无缓冲”、“行缓冲”或“完全缓冲”。

于 2013-07-15T15:39:53.943 回答