提问
除非换行符在格式字符串中,为什么
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 时,字符应尽快从源或目的地出现。否则,可以将字符作为块累积并发送到主机环境或从主机环境发送。
??
??当流完全缓冲时,当填充缓冲区时,字符将作为块传输到主机环境或从主机环境传输。
??
??当流行缓冲时,当遇到换行符时,字符将作为块传输到主机环境或从主机环境传输。
??
??此外,当填充缓冲区,在无缓冲流上请求输入时,或者在需要从主机环境传输字符的行缓冲流上请求输入时,字符旨在作为块传输到主机环境。 。
??
??对这些特性的支持是实现定义的,可能会受setbuf
和setvbuf
函数的影响。
其它参考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是缓冲的,因此只会在打印换行符后输出。
要获得即时输出,请:
- 打印到stderr。
- 使stdout无缓冲。
其它参考6
默认情况下,stdout是行缓冲的,stderr是无缓冲的,文件是完全缓冲的。
其它参考7
你可以fprintf到stderr,这是无缓冲的。或者你可以在你想要的时候冲洗stdout。或者您可以将stdout设置为无缓冲。
其它参考8
使用
setbuf(stdout, NULL);
禁用缓冲。