在编程时无意中发现一个有趣的现象,经过分析应该是标准IO流的缓冲区机制引起的。
有如下一段代码
#include <stdio.h>
#include <unistd.h>
int main() {
printf("#\n");
write(1, "123", 3);
}
它的输出如下
#
123
这段程序调用了printf和write两个函数,分别对应于带缓冲的流式IO和没有缓冲的直接IO。两个函数先后向屏幕输出“#\n”和“123”这两个字符串,这样的结果在我们的意料之中。
我们将上述代码中输出的字符串”#\n”改为”#” :
#include <stdio.h>
#include <unistd.h>
int main() {
printf("#");
write(1, "123", 3);
}
这回的输出还和原来一样吗?非常有趣的是它的输出变成了下面这样:
123#
两个字符串实际的输出顺序竟与代码中的输出顺序相反,是什么原因造成的呢?
没错,就是缓冲区。
我们知道在一般的linux系统中,标准输出流是行缓冲的,在第一段代码中printf函数写入缓冲区的字符串“#\n”以“\n”结束,代表写入的字符串已经到达一行的末尾,这时缓冲区中的内容会被立即写入标准输出,即显示在屏幕上。
而对于第二段代码printf函数向缓冲区写入字符串“#”,由于缓冲区中没有写入代表一行结束的字符‘\n’,所以缓冲区中的内容没有立即写入标准输出。之后调用write函数,由于它是直接IO,没有缓冲区,所以字符串“123”被直接写入标准输出,由于字符“\n”一直没有被写入标准输出流的缓冲区,所以直到程序结束要退出主函数时,缓冲区的内容才被写入标准输出。这就造成了我们看到的输出顺序相反的现象。