Windows与Linux标准输出流的区别
问题背景
在 Windows 和 Linux 上同时编译运行以下程序:
#include <stdio.h>
int main()
{
printf("hello world!!!");
while(1);
return 0;
}Windows 的执行结果:

Linux 的执行结果:

可以看到,在 Windows 中,循环之前打印了hello world,但是在 Linux 中,看起来似乎hello world没有被打印出来就直接开始循环了。
原因分析
首先,printf是一个行缓冲函数
该函数会先将内容写入缓冲区,当满足下面的条件之一时,才会将缓冲区的内容打印出来。
有输入,比如
printf之后马上用scanf,这种调用scanf等要从缓冲区中读取数据时,也会将缓冲区的数据刷新。遇到
'\n','\r'等,比如printf("hello world!!! \n")缓冲区填满
整个程序正常结束
调用
fflush或stdout手动刷新缓存区。(关于fflush函数的用法和如何刷新缓存区,此处不再赘述)
由上面的结果来看,Linux 的执行结果符合 printf函数的特性,但是 Windows 下却能正常输出。原因是什么?
经过查阅资料,该现象是由于 MS 实现的问题。MS的运行库不支持行缓冲,最本质的原因,printf调用的是操作系统的底层“ 系统调用 ”
而且当 stdout 是一个字符设备的时候,printf会立即输出。
查询 Linux 缓冲区大小
在 Linux 环境下,printf的缓冲区大小可以由以下方法查询:
查看stdio.h中的宏BUFSIZ大小:(同理:也可以调用其他宏查看。比如查看输入缓冲区大小,将stdout改为stdin即可)
#include <stdio.h>
int main() {
FILE *stream = stdout;
int buf_size;
// 查询缓冲区大小
setvbuf(stream, NULL, _IONBF, 0);
buf_size = BUFSIZ;
printf("stdout 缓冲区大小: %d 字节\n", buf_size);
return 0;
}我的 Linux ARM 开发板返回的结果是这样的:

代表我的缓冲区大小是 8K。
所以才会出现在 Linux 中,hello world并没有占满我的 8K 缓存,所以不会输出打印。
解决
解决方案一
添加换行符:
\n
#include <stdio.h>
int main()
{
printf("hello world!!! \n");
while(1);
return 0;
}结果:

解决方案二
使用
fflush函数
#include <stdio.h>
int main()
{
printf("hello world!!!");
fflush(stdout); // 刷新stdout缓冲区
while (1);
return 0;
}结果:
- 感谢你赐予我前进的力量
赞赏者名单
因为你们的支持让我意识到写文章的价值🙏
本文是原创文章,采用 CC BY-NC-ND 4.0 协议,完整转载请注明来自 超级帅气
评论
匿名评论
隐私政策
你无需删除空行,直接评论以获取最佳展示效果

