从stdin读取会刷新stdout吗?

18

当连接到终端时,stdout 是按行缓冲的,但我记得在某个地方读取(至少从stdin)会自动刷新 stdout。 所有我使用过的 C 实现都是这样做的,但我现在找不到它在标准中的说明。

它确实是有道理的,否则像这样的代码:

printf("Type some input: ");
fgets(line, sizeof line, stdin);

需要额外添加 fflush(stdout);

那么这里stdout是否保证被刷新?

编辑:

正如几个回复所说,标准中似乎没有保证在我的示例中stdout的输出将出现在stdin读取之前,但另一方面,此意图在(我免费的标准草案副本中)已声明:

交互式设备的输入和输出动态应按照7.19.3中指定的进行。 这些要求的目的是为了使未经缓冲或行缓冲的输出尽可能快地出现,以确保提示消息实际上在程序等待输入之前出现。

(ISO/IEC 9899:TC2 委员会草案 - 2005年5月6日,第14页)。

因此似乎没有保证,但在大多数实现中它可能仍能正常工作。(著名的最后一句话......)


1
跟随交叉引用到7.19.3(C11中的7.21.3)也是有用的,因为它提到了哪些输入操作会导致刷新。这些在https://dev59.com/jlkS5IYBdhLWcg3ws4nr#39536803上进行了讨论。 - Davis Herring
当谈到glibc实现时,答案是肯定的。 - Steve Lau
6个回答

5
不,它不会。

但通常我们看到的是在fgets行之前刷新stdout。那么,为什么它会在这里被刷新呢? - shadyabhi
标准似乎允许C实现在fgets之前不打印提示符,但“意图”是应该打印的,我认为大多数(全部?)实现都会这样做。 - Thomas Padron-McCarthy
遵循这个意图会使所有的输入变得更慢,而且收益不确定。 - R.. GitHub STOP HELPING ICE

5
回答你的问题,你需要在printf()调用后加上额外的fflush(stdout);以确保程序在尝试读取输入之前出现提示。从stdin读取不会为你执行fflush(stdout);

4
不需要。您需要使用fflush(stdout);许多实现会在将输出发送到终端时在每个换行符处刷新。

据我所知,标准要求 stdout 默认情况下是行缓存或无缓存的。 - Yakov Galka

4
没有,标准输入/输出都是有缓冲的。你需要明确调用 fflush(stdout) 以便将视频内存/Unix终端内存中的缓冲数据推送到视图设备(如终端)。可以通过调用 setvbuf 来设置数据的缓冲区。 编辑:感谢Jonathan,回答这个问题,从stdin读取不会刷新stdout。我可能在这里偏题了,因为我指定了演示如何使用setvbuf的代码。
  #include 
int main(void) { FILE *input, *output; char bufr[512];
input = fopen("file.in", "r+b"); output = fopen("file.out", "w");
/* 设置输入流以进行最小磁盘访问, 使用我们自己的字符缓冲区 */ if (setvbuf(input, bufr, _IOFBF, 512) != 0) printf("failed to set up buffer for input file\n"); else printf("buffer set up for input file\n");
/* 设置输出流进行行缓冲, 使用间接调用malloc获得的空间 */ if (setvbuf(output, NULL, _IOLBF, 132) != 0) printf("failed to set up buffer for output file\n"); else printf("buffer set up for output file\n");
/* 执行文件I/O操作 */
/* 关闭文件 */ fclose(input); fclose(output); return 0; }
希望这有所帮助, 最好的祝福, 汤姆。

你的代码如何与标准输入输出的行为相关联? - Jonathan Leffler
@Jonathan:这是一个使用setvbuf设置输入缓冲区为512或任何数字(最好在字边界上)的示例。这是从Borland C编译器帮助文件中提取的示例,展示了setvbuf的用法。 - t0mm13b
1
代码作为回答另一个问题是可以的——但它并没有回答所问的问题,即“从stdin读取是否会刷新stdout”。我不会因为你的回答离题而惩罚你,但我认为你的回答是离题的。 - Jonathan Leffler

2

不,这不是标准的一部分。当然,你可能使用了一个库实现,其中发生了你描述的行为,但这是一个非标准的扩展,你不应该依赖它。


1

注意,当在标准输入上读取或标准输出上写入时阻塞时,要小心处理进程间死锁。


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