大家好。对以下问题感兴趣。C 中标准流的输入/输出(stdin / stdout)是缓冲的,这意味着进入这些流的所有信息都累积在缓冲区中,然后写入文件(控制台)。我读到缓冲区已满时会发生录制。缓冲区大小是多少?我认为大小在几千字节左右波动,但是为什么,例如,如果有一个 printf() 函数后跟 scanf(),那么传输到 printf() 的内容会显示在屏幕上,而输出被缓冲并且缓冲区没有完全填满,或者仍然存在将缓冲区中的内容写入文件的时刻?对此,我也无法理解为什么需要flash()。请用简单的语言解释。谢谢
C 标准定义了三种流缓冲¹:
\n
),如果缓冲区已满或强制刷新,则输出。此外,当某些(通常是另一个,例如)行缓冲流尝试读取某些内容并且其输入缓冲区为空时,所有行缓冲输出流(特别是)都会被刷新。stdout
stdin
对于标准流,还保证:
stderr
没有完全缓冲。实际上,在几乎所有实现中,它都是无缓冲的。stdin
并且stdout
只有在它们不指向交互式设备时才能完全缓冲(即 I/O 被重定向到文件,而不是来自控制台/终端)。在几乎所有 POSIX 系统上,它们都是线性缓冲的。但是标准库的 msvc 实现不支持线性缓冲流,因此它们在那里没有缓冲。您可以使用 更改缓冲类型并设置自己的缓冲区
setvbuf()
。依赖于实现,它在宏中可用
BUFSIZ
。大小保证大于256,典型值:512-8k。但是这个缓冲区的内部结构和算法不是专门的,所以这并不意味着会从文件中读取/写入/写入这么多字节。如上所述,默认情况下,与终端关联的流要么是行缓冲的,要么是无缓冲的。在第一种情况下,输出
printf()
在当时立即出现在屏幕上,而在第二种情况下——如果它printf()
以新行结束,或者在执行时立即出现scanf()
。在此示例中可以看到行为上的差异:在 win32上,它也会
Hello
在 10 秒后显示world!
,而在 * nix 上,它也会在 10 秒后显示。与终端不同,文件通常是完全缓冲的,例如在这个版本中:
在延迟期间,
getc()
文件将为空。除了完全填充的情况外,当文件关闭时( )强制刷新缓冲区
fclose()
,程序正确终止(exit()
或return
从main()
,但不一定是何时abort()
)。此外,一些其他标准函数可以调用fflush()
,例如,fseek()
或从打开的文件中读取函数以进行读/写,但这已经取决于实现。fflush()
实际上需要强制将缓冲区的内容写入文件。在上面的例子中,如果你添加fflush()
beforegetc()
,它将"Hello world!"
保证被写入文件。如果你对术语再多找错,那么fflush()
缓冲区的内容会“传递给执行环境”,实际上这并不意味着它可以保证保存在磁盘上。操作系统有自己的缓冲设施。还值得记住的是,它只
fflush()
影响输出缓冲区,对输入流没有影响。¹ 通常,所有这些都是为输入流和输出流定义的,但实际上,这实际上不会影响输入流的行为。
默认情况下,输入和输出缓冲区是同步的。这意味着来自不同流的任何序列都必须具有已保存的序列。例如,如果缓冲"type x:"并按10,那么输出应该是"type x:10",而不是"10 type x:"。
如果它
scanf
要求数据,则默认情况下它会输出按下的字母,并且输出缓冲区与fflush
输出同步введите x:
。您可以禁用屏幕上输入字符的显示,然后为了让用户了解他们想要从他那里得到什么,那么您需要清除缓冲区,否则屏幕上将没有请求введите x:
。例如,当您要求输入密码时,就会发生这种情况。如果输出到文件,则数据将写入 C 缓冲区,但不会写入操作系统缓冲区。在同步期间,C 缓冲区被清除并写入 OS 缓冲区。所以更有可能在危急情况下将数据写入文件。(电/内存/处理器)