int main()
{
printf("Hello"); // doesn't display anything on the screen
printf("\n"); // hello is display on the screen
return 0;
}
在收到新行之前,所有字符(打印候选字符)都被缓冲?对的?
问题1-为什么在终端上打印之前要等到换行字符?
Q2-第一个printf(即
"Hello"
)的字符缓冲在哪里?问题3-打印流程是什么现在在哪里?司机?驱动程序是否有一个控件要等到\n?
Q4-附加到流程的角色标准输出是什么?
寻找深入的图片。如果有什么不合理的地方,请随意编辑问题。
最佳答案
我先从一些定义开始,然后回答你的问题。
文件:它是一个有序的字节序列。它可以是磁盘文件、程序生成的字节流(如管道)、TCP/IP套接字、从外围设备(如键盘或显示器)接收或发送到外围设备的字节流等。后两者是交互文件文件通常是程序与其环境通信的主要方式。
流:它是数据从一个地方流向另一个地方的一种表示,例如从磁盘流向存储器、存储器流向磁盘、一个程序流向另一个程序等。流是数据的来源,数据可以放入(写入)或取出(读取)因此,它是一个接口,用于将数据写入或从上述任何类型的文件中读取数据。在对文件执行任何操作之前,必须打开该文件。打开文件会将其与流关联。流由FILE
头中定义的stdio.h
数据类型表示。对象(它是一个结构)保存与关联文件连接有关的所有内部状态信息,包括文件位置指示器和缓冲信息。FILE
对象由输入/输出库函数在内部分配和管理,您不应该尝试创建自己的FILE
类型的对象,库会为我们这样做。程序应该只处理指向这些对象(FILE
)的指针,而不是对象本身。
缓冲区:缓冲区是属于一个流的内存块,用于暂时保存流数据。当对文件执行第一个I/O操作时,将调用FILE *
并获取缓冲区写入流的字符通常在缓冲区中累积(在以块的形式传输到文件之前),而不是在应用程序输出后立即出现类似地,流以块的形式从主机环境检索输入,而不是以字符为基础。这样做是为了提高效率,因为与内存操作相比,文件和控制台I/O速度较慢。malloc
库提供三个预定义的文本流(C
)打开并可在程序启动时使用。它们是FILE *
(标准输入流,是程序的正常输入源)、stdin
(标准输出流,用于程序的正常输出)和stdout
(标准错误流,用于程序发出的错误消息和诊断)。这些流是缓冲的还是非缓冲的是标准定义的实现,而不是必需的。stderr
提供三种类型的缓冲-无缓冲、块缓冲和行缓冲。无缓冲意味着字符一经写入(对于输出流)就出现在目标文件上,或者以字符为单位从文件中读取输入,而不是以块(对于输入流)为单位读取。块缓冲意味着字符保存在缓冲区中并作为块写入或读取。行缓冲意味着字符只在新行写入缓冲区或从缓冲区读取之前保存。GCC
和stdin
是块缓冲的,前提是可以确定它们不引用交互设备,否则它们是行缓冲的(任何流都是这样)。默认情况下,stdout
始终是无缓冲的。
标准库提供了更改流的默认行为的函数。您可以使用stderr
强制输出流缓冲区中的数据(fflush
对于输入流未定义)您可以使用fflush
函数使流无缓冲。
现在,我们来问你的问题。
未标记的问题:是,因为setbuf
通常指显示终端,除非您使用stdout
运算符进行输出重定向。
问题1:它等待,因为当它引用终端时,>
是换行缓冲的。
问题2:字符是在分配给stdout
流的缓冲区中缓冲的。
问题3:打印流程为:内存-->stdout
缓冲区-->显示终端有内核缓冲区,也由操作系统控制,数据在出现在终端之前经过这些操作系统。
Q4:stdout
是指通常是终端的标准输出流。
最后,这里有一个示例代码,在我完成我的答案之前进行实验。
#include <stdio.h>
#include <limits.h>
int main(void) {
// setbuf(stdout, NULL); // make stdout unbuffered
printf("Hello, World!"); // no newline
// printf("Hello, World!"); // with a newline
// only for demonstrating that stdout is line buffered
for(size_t i = 0; i < UINT_MAX; i++)
; // null statement
printf("\n"); // flush the buffer
return 0;
}