默认情况下,stdout 行是缓冲的、无缓冲的还是不确定的?

Posted

技术标签:

【中文标题】默认情况下,stdout 行是缓冲的、无缓冲的还是不确定的?【英文标题】:Is stdout line buffered, unbuffered or indeterminate by default? 【发布时间】:2011-04-13 00:49:22 【问题描述】:

c997.9.13/7 部分指出:

在程序启动时,三个文本流是预定义的,不需要显式打开 - 标准输入(用于读取常规输入)、标准输出(用于写入常规输出)和标准错误(用于写入诊断输出)。

最初打开时,标准错误流没有完全缓冲;当且仅当可以确定流不引用交互式设备时,标准输入和标准输出流才会被完全缓冲。

所以这是有道理的。如果您将标准输出推送到文件中,您希望它完全缓冲以提高效率。

但是当您无法确定设备是非交互式的(即正常输出到终端)时,我在标准中找不到关于输出是行缓冲还是非缓冲的提及.

我问的原因是对我的回答 here 的评论,我应该在两个语句之间插入一个 fflush(stdout);

printf ("Enter number> ");
// fflush (stdout); needed ?
if (fgets (buff, sizeof(buff), stdin) == NULL)  ... 

因为我没有用换行符终止 printf。谁能解决这个问题?

【问题讨论】:

【参考方案1】:

C99 标准没有指定三个标准流是无缓冲的还是行缓冲的:这取决于实现。我知道的所有 UNIX 实现都有一个行缓冲stdin。在 Linux 上,stdout 行缓冲,stderr 无缓冲。

据我所知,POSIX 没有施加额外的限制。 POSIX 的 fflush 页面确实在示例部分中注明:

[...] 使用 fflush() 函数是因为标准输出通常是缓冲的,提示可能不会立即打印在输出或终端上。

所以你添加fflush(stdout);的注释是正确的。


另一种方法是使 stdout 无缓冲:

setbuf(stdout, NULL);
/* or */
setvbuf(stdout, NULL, _IONBF, 0);

但正如 R. 所说,您只能执行一次此操作,并且必须在您写信给 stdout 或对其执行任何其他操作之前。 (C99 7.19.5.5 2)


我刚刚在comp.lang.c 上读到了recent thread 关于同样的事情。备注之一:

Unix 约定是 stdinstdout 在与终端关联时是行缓冲的,否则是全缓冲的(也就是块缓冲的)。 stderr 始终没有缓冲。

【讨论】:

您不能“暂时”使stdout 无缓冲。 setbufsetvbuf 具有未定义的行为,除非它们是文件打开后对其执行的第一个操作。 在行缓冲的情况下,是否存在高水位线,如果行太长会被刷新? @CMCDragonkai 默认行缓冲区大小是实现定义的,取决于它指向的内容(管道的缓冲区大小与终端或文件不同)。更多详情***.com/questions/10904067/… “在 Linux 上,stdout 是行缓冲的”——仅当它是 TTY 时。

以上是关于默认情况下,stdout 行是缓冲的、无缓冲的还是不确定的?的主要内容,如果未能解决你的问题,请参考以下文章

85.缓冲区设置

搞懂 fflush(stdout)

linux文件缓冲区

stdout和stderr标准输出的区别

禁用输出缓冲

如何在 Perl 中读取和写入大缓冲区到进程 stdin/stdout/stderr?