为了账号安全,请及时绑定邮箱和手机立即绑定

除非换行符在格式字符串中,为什么printf在调用后不会刷新?

除非换行符在格式字符串中,为什么printf在调用后不会刷新?

12345678_0001 2019-05-23 13:11:20
printf除非换行符在格式字符串中,为什么在调用后不刷新?这是POSIX的行为吗?我怎么可能printf每次都立即冲洗?
查看完整描述

3 回答

?
胡说叔叔

TA贡献1804条经验 获得超8个赞

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);


查看完整回答
反对 回复 2019-05-23
?
qq_遁去的一_1

TA贡献1725条经验 获得超7个赞

不,它不是POSIX行为,它是ISO行为(嗯,它 POSIX行为,但只在它们符合ISO的范围内)。

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

myprog >myfile.txt

这对效率很有意义,因为如果您与用户进行交互,他们可能希望看到每一行。如果您将输出发送到文件,则很可能是另一端没有用户(尽管不是不可能,但他们可能正在拖尾文件)。现在你可以争辩说用户想要看到每个角色但是有两个问题。

首先是它效率不高。第二个原因是ANSI C的原始授权主要是对现有行为进行编码,而不是发明行为,而这些设计决策是在ANSI开始流程之前做出的。在改变标准中的现有规则时,即便是ISO现在也非常谨慎。

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

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

setvbuf (stdout, NULL, _IONBF, BUFSIZ);

只要记住这可能会影响性能相当多,如果你正在发送输出到文件。另请注意,对此的支持是实现定义的,不受标准保证。

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

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

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

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

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

对这些特性的支持是实现定义的,并且可能通过setbufsetvbuf函数受到影响。


查看完整回答
反对 回复 2019-05-23
?
天涯尽头无女友

TA贡献1831条经验 获得超9个赞

这可能是因为效率,因为如果你有多个程序写入单个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

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


查看完整回答
反对 回复 2019-05-23
  • 3 回答
  • 0 关注
  • 643 浏览

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信