C 为什么是标准输出缓冲?

C 为什么是标准输出缓冲?,c,libuv,C,Libuv,我正在尝试学习libuvapi,并编写了以下测试: #include <stdio.h> #include <stdlib.h> #include <uv.h> void timer_cb(uv_timer_t* timer) { int* i = timer->data; --*i; if(*i == 0) { uv_timer_stop(timer); } printf("timer %d\n"

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

#include <stdio.h>
#include <stdlib.h>
#include <uv.h>

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;
}
#包括
#包括
#包括
无效计时器\u cb(紫外线计时器\u t*计时器){
int*i=定时器->数据;
--*一,;
如果(*i==0){
紫外线定时器停止(定时器);
}
printf(“计时器%d\n”,*i);
//fflush(stdout);
}
int main(){
uv_loop_t*loop=uv_default_loop();
uv_timer_t*timer=malloc(sizeof(uv_timer_t));
uv_定时器_init(循环,定时器);
int i=5;
计时器->数据=&i;
紫外线定时器启动(定时器,定时器cb,1000,2000);
uv_运行(循环,uv_运行默认值);
printf(“正在退出。\n”);
uv_关闭(计时器,0);
uv_回路_闭合(回路);
返回0;
}
当运行它时,在程序完成运行之前不显示任何输出,然后立即显示所有输出。如果我取消注释
fflush
行,它将按预期工作,每2秒写入一次


有人能给我解释一下吗?为什么在换行后,
stdout
没有像前面解释的那样在其他地方刷新?为什么我需要手动刷新它?

流缓冲是实现定义的

根据7.21.3文件,第3段:

当一条溪流 无缓冲的字符旨在尽快从源位置或目标位置出现。否则字符 可累积并传输到主机或从主机传输 将环境视为块。当一条溪流 完全缓冲,当缓冲区填满时,字符将作为块传输到主机环境或从主机环境传输。当 溪流是 行缓冲,当新行出现时,字符将作为块传输到主机环境或从主机环境传输 遇到字符。此外,字符的目的是 当缓冲区被激活时,作为块传输到主机环境 在非缓冲流上请求输入时,或 在需要的行缓冲流上请求输入 从主机传输字符 环境对这些特性的支持是 已定义实施,并可能通过
setbuf
setvbuf
函数


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

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

C11(N1570)7.21.3/7文件:

初始打开时,标准错误流没有完全缓冲; 标准输入和标准输出流在以下情况下完全缓冲: 并且仅当可以确定流不引用 交互式设备

C11(N1570)5.1.2.3/7程序执行:

交互设备的构成由实现定义

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

setvbuf(stdout, buff, _IOLBF, size);
其中,
buff
被声明为
size
元素(例如1024)的字符数组


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

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

“为什么stdout缓冲”-为什么不?这个答案可能对您有用:@AndrewHenle窗口,打开mingw64msys@Olaf我明白了(见最后我链接的答案)缓冲区在newline@baruch:您在标准中的什么地方找到的?我使用
setvbuf(stdout,NULL,_IOLBF,0)将其设置为行缓冲但它仍然不起作用。只有当我将其设置为无缓冲(
\u IONBF
)时,才会执行此操作work@baruch:AFAIR,
setvbuf
需要为其提供自备的缓冲区。否则,它将无法工作。我使用
setvbuf(stdout,NULL,_IOLBF,0)将其设置为行缓冲但它仍然不起作用。只有当我将它设置为无缓冲(
\u IONBF
)时,它才会像该答案中的链接一样工作,在Windows上没有行缓冲。我想这就是问题所在,但这并不能回答这个问题。若要评论或要求作者澄清,请在其帖子下方留下评论。-我认为它包括两个答案:使用setvbuf或stderr。第三个答案只是暗示,用来解释为什么系统将stdout误认为是非交互式的。