为什么 printf 可以自行打印,却要在 printf 后使用 fflush?

4

我是C语言新手,如果我的问题太基础请见谅。我经常看到如下代码:

printf("%d", counter);
fflush(stdout);

我猜测如果缓冲区未满,它将不会输出内容,因此您需要刷新 stdout。但是,我尝试仅使用 printf 而不使用 fflush,仍然在屏幕上打印输出,那么使用 flush 的意义何在?


2
程序在这段代码之后很快就退出了吗?打开的句柄在关闭时都会被刷新,包括程序退出时,输出将会出现。当程序不会很快退出时,fflush 很重要,你可能需要立即在屏幕上显示输出,例如显示倒计时(使用 \r 反复擦除并更新),或确保数据被发送到并行进程依赖的管道中(特别是如果你将等待对该数据的响应;如果你在不刷新的情况下阻塞,它永远不会看到数据,也永远不会响应,你就会陷入死锁)。 - ShadowRanger
我试着不看路就过马路,结果一切都很好,那为什么人们过马路前要左右看呢? - David Schwartz
@dukeforever:那跟什么有关系呢?OP正在使用stdout,它既不是输入流也不是更新流,而是纯输出。 - ShadowRanger
1
你的逻辑有一个微妙的错误,slowjams;或者,也许只是措辞上的错误。你认为缓冲区只有在满时才会被刷新。这并不完全正确。是的,满缓冲区会触发刷新;但是,即使缓冲区没有满,更长时间的停留和剩余计算/IO容量的数量也会导致缓冲区刷新。 - Edwin Buck
3
除了fflush以外,没有其他保证会触发缓冲区刷新的方法。其他所有操作都可能会触发刷新,但不能保证。某些流在写入时会自动刷新(在某些语言中)。通常这些是错误流,而不是常规输出流;但是,为确保其保证行为,您需要查阅语言文档。 - Edwin Buck
显示剩余2条评论
1个回答

10
printf 往往会在某个时刻显示信息,因为所有对 printf 的输出都被缓冲了起来。使用 fflush 能够保证缓冲区被清空,这意味着当调用 fflush 的那一行代码执行时,printf 语句已经被输出。
在可能出现崩溃的程序中,fflush 是一个非常有用的工具。通常情况下用户希望在程序崩溃之前能够获得最后输出的信息。如果程序中没有使用 fflush,那么这些输出语句就很可能会因为还在缓冲区中而没有被及时显示给用户。
这往往会导致开发者在分析崩溃日志文件时,错误地在程序源代码的错误位置寻找问题。因为心理上认为“它没办法运行到这里,因为我们本应该看到一个 printf 语句”,而实际上程序在输出这个语句后就崩溃了,而这个信息却还留存在缓冲区中。如果在输出语句后立即清空缓冲区,这种情况就不会发生(尽管程序的运行速度会变慢,因为清空缓冲区需要时间)。

2
值得注意的是,默认情况下,stderr 不带缓冲。因此,所描述的问题仅存在于 stdout 而非 stderr - Andreas Wenzel

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接