使用 fflush(stdout) 和不使用它有什么不同

what is the different of using fflush(stdout) and not using it

#include <stdio.h>

int main()
{
   printf("Hello");
   fflush(stdout);
   return 0;
}
#include <stdio.h>

int main()
{
   printf("Hello");
   return 0;
}

我想了解 fflush(stdout) 的用法以及上面两个程序之间的区别是什么?

stdout 指向 tty 时,它默认为 line-buffered。这意味着输出在 计算机内部 内缓冲,直到接收到整行(并输出)。

您的程序没有向计算机内部发送整行。

在使用 fflush() 的情况下,您是在告诉 计算机内部 将缓冲区中的当前数据发送到设备;如果没有 fflush(),您将依赖 计算机内部结构 在程序终止时为您执行此操作。

计算机内部结构 我的意思是 C 库、操作系统、硬件接口、各种接口之间的(自动)缓冲区的组合,...

在现代 OS 上的普通 C 程序 运行 中,文件访问被缓冲两次(或更多,当您计算像驱动器中的缓冲区这样的缓冲区时)。一个缓冲区在FILE结构中实现,另一个在内核中实现。

通常,FILE 结构会将内容缓冲在程序内部的缓冲区中。当您向缓冲文件写入内容时,内容会保留在 运行 程序内部的缓冲区中。当缓冲区已满时,它被写入 OS,当缓冲模式为行缓冲时,在一行的末尾。此数据通过系统调用写入 OS,例如 write()。 缓冲区在那里是因为系统调用需要从用户程序到内核的上下文切换,这是相对昂贵的(慢),缓冲区在这里是为了减少系统调用的次数。您也可以在没有 stdio 函数的情况下直接使用程序中的系统调用,但是,此函数的可移植性较差且处理起来更复杂。 fflush(stdout) 检查缓冲区中是否有任何应写入的数据,如果有,则使用底层系统调用将数据写入 OS.

当系统调用returns时,数据在你的内核中。但现代操作系统也会缓冲这些数据。这用于减少磁盘写入次数,减少延迟和其他事情。此缓冲区完全独立于程序中的 FILE 缓冲区。

请注意,这并不适用于所有系统。例如,微控制器环境可能会提供一些直接写入 UART 的 stdio.h 函数,没有任何缓冲区,既不在 FILE 内部,也不在任何(可能不存在的)OS.

要查看 fflush() 对 运行 程序的作用,请比较以下程序:

int main(void)
{
  fputs("s",stdout);
  fputs("e",stderr);
}

int main(void)
{
  fputs("s",stdout);
  fflush(stdout);
  fputs("e",stderr);
}

在Linux上,stderr默认不缓冲,所以fputs("e",stderr);会立即打印数据。另一方面,fputs("s",stdout); 默认情况下在 Linux 上进行行缓冲,因此不会立即打印数据。这导致第一个程序输出 es 而不是 se,但第二个程序输出 se.

您可以使用 setvbuf()

更改缓冲模式