我正在尝试学习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 %dn", *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
没有刷新换行符,正如此处和其他地方所解释的那样?为什么我需要手动刷新它?
流缓冲是实现定义的。
根据 C 标准第7.21.3文件第 3 段:
当流未缓冲的字符旨在尽快从源或目标位置显示。 否则字符 可以累积并传输到主机或从主机传输 环境作为块。 当流完全缓冲的字符旨在在填充缓冲区时作为块传输到主机环境或从主机环境传输。 当一个 流是 行缓冲,字符旨在作为块传输到主机环境,当换行符时 遇到角色。 此外,字符旨在 当缓冲区 填充,当在未缓冲的流上请求输入时,或者当 在需要的行缓冲流上请求输入 从主机传输字符 环境。对这些特征的支持是 实现定义,并且可能通过
setbuf
和setvbuf
功能。
缓冲的类型取决于您的实现,并且您的实现在您的示例中显然不是行缓冲。
没有严格的要求,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
。
出于某种原因,您的系统决定您的标准输出不是交互式的。您是否正在对标准输出进行一些奇怪的重定向或对您的终端做一些奇怪的事情?您应该能够使用 setbuf 进行覆盖,或者您可以使用 stderr 而不是 stdout。