提问



除非换行符在格式字符串中,为什么printf在调用后不会刷新?这是POSIX的行为吗?我怎么可能printf每次都立即冲洗?

最佳参考


stdout流被缓冲,因此只会在到达换行符后(或者告诉它时)显示缓冲区中的内容。您可以选择立即打印:


使用fprintf打印到stderr:


fprintf(stderr, "I will be printed immediately");


在需要时使用fflush刷新标准输出:


printf("Buffered, will be flushed");
fflush(stdout); // Will now print everything in the stdout buffer


编辑:从下面的Andy Ross的评论中,您还可以使用setbuf禁用stdout上的缓冲:


setbuf(stdout, NULL);

其它参考1


不,它不是POSIX行为,它是ISO行为(好吧,它是 POSIX行为,但只有它们符合ISO)。


标准输出是行缓冲的,如果可以检测到它是指交互式设备,否则它是完全缓冲的。所以有些情况下printf不会刷新,即使它有一个新行发送,例如如:


myprog >myfile.txt


这对效率很有意义,因为如果您与用户交互,他们可能希望看到每一行。如果您将输出发送到文件,那么很可能在另一方没有用户结束(虽然不是不可能,但他们可能会拖尾文件)。现在你可以认为用户想要看到每个角色但是有两个问题。


第一个是效率不高。第二个原则是ANSI C的主要任务是主要编纂现有的行为,而不是发明新的行为,而那些设计在ANSI开始这个过程之前很久就已经做出了决定。甚至ISO在改变标准中的现有规则时也非常谨慎。


至于如何处理,如果你fflush (stdout)在你想立即看到的每个输出调用之后,那将解决问题。


或者,您可以在stdout上操作之前使用setvbuf,将其设置为无缓冲,并且您不必担心将所有这些fflush行添加到您的代码中:


setvbuf (stdout, NULL, _IONBF, BUFSIZ);


请记住,如果 将输出发送到文件,可能会影响性能。另请注意,对此的支持是实现定义的,不受标准保证。


ISO C99部分7.19.3/3是相关位:



??当流 unbuffered 时,字符应尽快从源或目的地出现。否则,可以将字符作为块累积并发送到主机环境或从主机环境发送。

??
??当流完全缓冲时,当填充缓冲区时,字符将作为块传输到主机环境或从主机环境传输。

??
??当流行缓冲时,当遇到换行符时,字符将作为块传输到主机环境或从主机环境传输。

??
??此外,当填充缓冲区,在无缓冲流上请求输入时,或者在需要从主机环境传输字符的行缓冲流上请求输入时,字符旨在作为块传输到主机环境。 。

??
??对这些特性的支持是实现定义的,可能会受setbufsetvbuf函数的影响。


其它参考2


这可能是因为效率,因为如果你有多个程序写入一个TTY,这样你就不会在一行上交换字符。因此,如果程序A和B正在输出,您通常会得到:


program A output
program B output
program B output
program A output
program B output


这很糟糕,但它比


proprogrgraam m AB  ououtputputt
prproogrgram amB A  ououtputtput
program B output


请注意,它甚至不能保证在换行符上刷新,因此如果刷新对您很重要,则应明确刷新。

其它参考3


要立即刷新呼叫fflush(stdout)fflush(NULL)(NULL表示刷新所有内容)。

其它参考4


注意:Microsoft运行时库不支持行缓冲,因此printf("will print immediatelly to terminal"):


http://msdn.microsoft.com/en-us/library/86cebhfs.aspx[27]

其它参考5


stdout是缓冲的,因此只会在打印换行符后输出。


要获得即时输出,请:



  1. 打印到stderr。

  2. 使stdout无缓冲。


其它参考6


默认情况下,stdout是行缓冲的,stderr是无缓冲的,文件是完全缓冲的。

其它参考7


你可以fprintf到stderr,这是无缓冲的。或者你可以在你想要的时候冲洗stdout。或者您可以将stdout设置为无缓冲。

其它参考8


使用setbuf(stdout, NULL);禁用缓冲。