关于在C中打印字符

时间:2014-02-27 06:07:12

标签: c printf puts

int main()
{
    printf("Hello"); // doesn't display anything on the screen

    printf("\n"); // hello is display on the screen

    return 0;
}

所有字符(打印候选)都被缓冲,直到收到新行?正确的吗?

Q1 - 为什么它会在终端上打印之前等待直到换行符?

Q2 - 第一个printf(即"Hello")的字符在哪里被缓冲?

问题3 - 什么是打印流程printf()->puts()->putchar() - >现在哪里?驱动程序?驱动程序是否有控制权等待\ n?

问题4 - 附加到流程的角色stdout是什么?

寻找深入的图片。如果某些事情没有意义,请随意编辑问题。

4 个答案:

答案 0 :(得分:3)

printf不直接写入屏幕,而是写入输出流,默认情况下是缓冲的。原因是,甚至可能没有连接屏幕,输出也可以转到文件。出于性能原因,如果对磁盘的访问进行缓冲,然后使用适当大小的块执行一步,而不是每次都写入,那么系统会更好。

您甚至可以更改缓冲区的大小并将其设置为0,这意味着所有输出都直接转到目标,这可能对记录有用。

setbuf(stdout, NULL);

缓冲区在已满时刷新,或者某些标准已满,如打印换行符。因此,当您在循环中执行printf时,您会注意到它将以块的形式写出,除非您在其间有换行符。

答案 1 :(得分:1)

是的,默认情况下,标准输出在连接到终端时是行缓冲的。缓冲区由操作系统管理,通常您不必担心它。

您可以使用setbuf() or setvbuf()更改此行为,例如,将其更改为无缓冲区:

setbuf(stdout, NULL);

printfputsputchar的所有功能都输出到标准输出,因此它们使用相同的缓冲区。

答案 2 :(得分:1)

如果您愿意,可以通过调用

清除新行前的字符
fflush(stdout);

如果您正在慢慢打印类似于进度条的内容,如果没有换行符打印每个字符,这可能很方便。

int main()
{
    printf("Hello"); // Doesn't display anything on the screen
    fflush(stdout);  // Now, hello appears on the screen
    printf("\n");    // The new line gets printed
    return 0;
}

答案 3 :(得分:1)

我将从一些定义开始,然后继续回答你的问题。

文件:这是一个有序的字节序列。它可以是磁盘文件,由程序(例如管道)生成的字节流,TCP / IP套接字,从外围设备(例如键盘或显示器)接收或发送到外围设备的字节流等。后两者是交互式文件。文件通常是程序与其环境通信的主要手段。

:它表示从一个位置另一个的数据流,例如,从磁盘到内存,从内存到磁盘一个程序到另一个程序等。流是数据源,其中数据可以放入(写入)或从(读取)数据中取出。因此,它是用于将数据写入文件或从文件读取数据的接口,该文件可以是如上所述的任何类型。在对文件执行任何操作之前,必须先打开该文件。打开文件会将其与流关联。流由FILE标头中定义的stdio.h数据类型表示。 FILE对象(它是一个结构)包含有关与相关文件的连接的所有内部状态信息,包括文件位置指示符和缓冲信息等内容。 FILE对象由输入/输出库函数在内部分配和管理,您不应该尝试创建自己的FILE类型的对象,库为我们做。程序应该只处理指向这些对象的指针(FILE *)而不是对象本身。

缓冲区:缓冲区是属于流的内存块,用于临时保存流数据。在文件上发生第一次I / O操作时,将调用malloc并获取缓冲区。写入流的字符通常在缓冲区中累积(在以块的形式传输到文件之前),而不是在应用程序输出后立即出现。类似地,流以块为单位而不是逐个字符地从主机环境检索输入。这样做是为了提高效率,因为与内存操作相比,文件和控制台I / O速度较慢。

C库提供了三个预定义的文本流(FILE *),可以在程序启动时使用。这些是stdin(标准输入流,它是程序的正常输入源),stdout(标准输出流,用于程序的正常输出)和{{ 1}}(标准错误流,用于程序发出的错误消息和诊断)。这些流是缓冲还是非缓冲是实现定义的,而不是标准所要求的。

stderr提供三种类型的缓冲 - 无缓冲,块缓冲和行缓冲。无缓冲意味着一旦写入(对于输出流)字符就出现在目标文件上,或者逐个字符地从文件读取输入而不是读取块(对于输入流)。块缓冲意味着字符被保存在缓冲区中并作为块写入或读取。行缓冲意味着只有在缓冲区中写入或读取换行符之前才会保存字符。

GCCstdin是块缓冲的,当且仅当他们可以确定不引用交互式设备时,他们才会进行行缓冲(任何流都是如此)。默认情况下,stdout始终是无缓冲的。

标准库提供了更改流的默认行为的函数。您可以使用stderr强制数据输出流缓冲区(fflush未定义输入流)。您可以使用fflush函数使流无缓冲。

现在,让我们来回答您的问题

无标记的问题:是的,因为setbuf通常是指显示终端,除非您使用stdout运算符进行输出重定向。

Q1:它等待,因为>在引用终端时是换行符。

Q2:在分配给stdout流的缓冲区中,字符被缓冲。

Q3:打印流程为:内存 - > stdout缓冲区 - >显示终端。存在由OS控制的内核缓冲区,数据在出现在终端之前通过。

问题4:stdout是指标准输出流,通常是终端。

最后,这是一个示例代码,用于在我完成答案之前对事物进行实验。

stdout