为什么stdout缓冲?

我正在尝试学习libuv api并编写以下测试:

 #include  #include  #include  void timer_cb(uv_timer_t* timer) { int* i = timer->data; --*i; if(*i == 0) { uv_timer_stop(timer); } printf("timer %d\n", *i); //fflush(stdout); } int main() { uv_loop_t* loop = uv_default_loop(); uv_timer_t* timer = malloc(sizeof(uv_timer_t)); uv_timer_init(loop, timer); int i = 5; timer->data = &i; uv_timer_start(timer, timer_cb, 1000, 2000); uv_run(loop, UV_RUN_DEFAULT); printf("Now quitting.\n"); uv_close(timer, 0); uv_loop_close(loop); return 0; } 

运行时,在程序运行完毕之前不会显示任何输出,然后立即显示所有输出。 如果我取消注释fflush线它按预期工作,每2秒写一次。

有人可以向我解释一下吗? 为什么stdout在换行后没有刷新,如此处和其他地方所解释的那样? 为什么我需要手动冲洗它?

流缓冲是实现定义的。

7.21.3文件 , C标准第3段:

当流是无缓冲的时 ,字符应尽快从源或目的地出现。 否则,可以将字符作为块累积并发送到主机环境或从主机环境发送。 当流被完全缓冲时 ,当填充缓冲区时,字符旨在作为块传输到主机环境或从主机环境传输。 当流被行缓冲时 ,当遇到换行符时 ,字符将作为块传输到主机环境或从主机环境传输。 此外,当填充缓冲区,在无缓冲流上请求输入时,或者在需要从主机环境传输字符的行缓冲流上请求输入时,字符旨在作为块传输到主机环境。 。 对这些特性的支持是实现定义的 ,可能会受到setbufsetvbuf函数的影响。

缓冲的类型取决于您的实现,并且您的实现显然不是您的示例中的行缓冲。

没有严格的要求, stdout是行缓冲的。 它也可以完全缓冲(或根本不缓冲),在这种情况下\n不会触发刷新流。

C11(N1570)7.21.3 / 7 档案

最初打开时,标准错误流未完全缓冲; 当且仅当可以确定流不参考交互设备时,标准输入和标准输出流是完全缓冲的。

C11(N1570)5.1.2.3/7 程序执行

构成交互设备的是实现定义的。

您可以尝试通过setvbuf标准函数强制执行特定类型的缓冲。 例如,要为stdout设置行缓冲,您可以尝试使用:

 setvbuf(stdout, buff, _IOLBF, size); 

其中buff被声明为size元素的字符数组(例如1024)。

请注意,必须在对流执行的任何其他I / O操作之前调用setvbuf

出于某种原因,您的系统决定您的stdout不是交互式的。 你在做什么奇怪的重定向stdout或做一些奇怪的终端? 您应该能够使用setbuf覆盖,或者您可以使用stderr而不是stdout。