标准I/O的三种缓冲
2016-01-26 16:33
330 查看
最近,有几个同学让我看了一个程序,后来发现问题都是出在使用printf()函数进行输出时的缓冲模式造成的。比如这样的程序:
#include
<stdio.h>
int main()
{
fprintf(stout,"1234");
while(1);
return 0;
}
程序并不是很长,但是就这样的程序出现了一个问题:为什么进入死循环之后,并没有输出“1234”,这个与我们预想的完全不一样,还以为是自己的程序写错了,可是看了又看,就三行代码,怎么会出错呢?原来这个就是标准I/O的缓冲模式造成的。
基于流的标准I/O的缓冲模式有三种:全缓冲,半缓冲,无缓冲。
全缓冲:直到缓冲区被填满,才调用系统I/O函数。对于读操作来说,直到读入的内容的字节数等于缓冲区大小或者文件已经到达结尾,才进行实际的I/O操作,将外存文件内容读入缓冲区;对于写操作来说,直到缓冲区被填满,才进行实际的I/O操作,缓冲区内容写到外存文件中。磁盘文件通常是全缓冲的。
行缓冲:直到遇到换行符'\n',才调用系统I/O库函数。对于读操作来说,遇到换行符'\n'才进行I/O操作,将所读内容读入缓冲区;对于写操作来说,遇到换行符'\n'才进行I/O操作,将缓冲区内容写到外存中。由于缓冲区的大小是有限的,所以当缓冲区被填满时,即使没有遇到换行符'\n',也同样会进行实际的I/O操作。标准输入stdin和标准输出stdout默认都是行缓冲的。
无缓冲:没有缓冲区,数据会立即读入或者输出到外存文件和设备上。标准出错stderr是无缓冲的,这样保证错误提示和输出能够及时反馈给用户,供用户排除错误。
看了这个应该明白了,原来这个是行缓冲造成的。我们是试着把
fprintf(stout,"1234");
改为
fprintf(stout,"1234\n");
这样的话,当我们陷入死循环之前,"1234"已经显示在标准输出上了。或者我们把
fprintf(stout,"1234");
改为
fprintf(stderr,"1234");
这个结果和上面的结果是一样的,只不过显示在了标准错误输出上了。
如果你不想按照上面的两种修改方式进行,也可以按照下面的方式,将I/O的缓冲设置为无缓冲方式。
#include
<stdio.h>
int main()
{
setbuf(stdout,
NULL);
fprintf(stout,
"1234");
while(1);
return 0;
}
这样修改之后的结果与前面两种方式修改之后的结果是一样的。
#include
<stdio.h>
int main()
{
fprintf(stout,"1234");
while(1);
return 0;
}
程序并不是很长,但是就这样的程序出现了一个问题:为什么进入死循环之后,并没有输出“1234”,这个与我们预想的完全不一样,还以为是自己的程序写错了,可是看了又看,就三行代码,怎么会出错呢?原来这个就是标准I/O的缓冲模式造成的。
基于流的标准I/O的缓冲模式有三种:全缓冲,半缓冲,无缓冲。
全缓冲:直到缓冲区被填满,才调用系统I/O函数。对于读操作来说,直到读入的内容的字节数等于缓冲区大小或者文件已经到达结尾,才进行实际的I/O操作,将外存文件内容读入缓冲区;对于写操作来说,直到缓冲区被填满,才进行实际的I/O操作,缓冲区内容写到外存文件中。磁盘文件通常是全缓冲的。
行缓冲:直到遇到换行符'\n',才调用系统I/O库函数。对于读操作来说,遇到换行符'\n'才进行I/O操作,将所读内容读入缓冲区;对于写操作来说,遇到换行符'\n'才进行I/O操作,将缓冲区内容写到外存中。由于缓冲区的大小是有限的,所以当缓冲区被填满时,即使没有遇到换行符'\n',也同样会进行实际的I/O操作。标准输入stdin和标准输出stdout默认都是行缓冲的。
无缓冲:没有缓冲区,数据会立即读入或者输出到外存文件和设备上。标准出错stderr是无缓冲的,这样保证错误提示和输出能够及时反馈给用户,供用户排除错误。
看了这个应该明白了,原来这个是行缓冲造成的。我们是试着把
fprintf(stout,"1234");
改为
fprintf(stout,"1234\n");
这样的话,当我们陷入死循环之前,"1234"已经显示在标准输出上了。或者我们把
fprintf(stout,"1234");
改为
fprintf(stderr,"1234");
这个结果和上面的结果是一样的,只不过显示在了标准错误输出上了。
如果你不想按照上面的两种修改方式进行,也可以按照下面的方式,将I/O的缓冲设置为无缓冲方式。
#include
<stdio.h>
int main()
{
setbuf(stdout,
NULL);
fprintf(stout,
"1234");
while(1);
return 0;
}
这样修改之后的结果与前面两种方式修改之后的结果是一样的。
相关文章推荐
- 一键生成各种尺寸Icon的php脚本
- 莫比乌斯反演定理证明
- QTP之excel操作函数整理
- Flowchart.js首页、文档和下载 - 流程图插件 - 开源中国社区
- ALTERA系列FPGA时序分析(二)
- 转: Oracle Form 中commit 与do_key('commit_form')区别
- (转)sqlplus中文显示乱码的问题
- leetcode 301. Remove Invalid Parentheses
- jqeury数据缓存之data()解析
- CentOS Linux下VNC Server远程桌面配置详解
- 【LEETCODE】313-Super Ugly Number [Python]
- 补充 十进制转化十六进制
- HDU【2795】Billboard
- DebugView 远程/服务器 Invalid argument:c
- 多线程之Thread--JAVA
- HTML,CSS和JavaScript对比(一)
- 期末练习赛 构造数列 数学+模拟(兰福德数列)
- 猫猫学Swift之变量和常量(2)
- 感知机学习
- EmptyResult类型