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 协议,完整转载请注明来自 超级帅气
评论
匿名评论
隐私政策
你无需删除空行,直接评论以获取最佳展示效果