标准I/O缓存的一些理解

1、关于标准I/O库的缓存:
在Lnix平台上,标准I/O库的作用就是为了尽可能减少使用read和write系统调用的数量。同时,在不同的系统平台上,还存在着选择最优缓冲区长度的问题,有了标准I/O库之后,所有这一切都交给标准I/O库去处理了,对程序员隐藏了不必要的复杂性。但是,标准I/O库也存在着一些比较晦涩的地方。

首先,我们知道,标准I/O有三种缓存方式:全缓存,行缓存,无缓存对磁盘上的文件而言,一般是采用的全缓存,也就是在数据填满缓冲区或者调用了fflush()之后数据才写到磁盘上;而当流涉及的是终端,比如标准输入或标准输出时,采用的则是行缓存,即仅当输入或输出遇到一个换行符时才执行I/O操作;而无缓存则相当于直接进行write调用。我们来看下面这段代码:
printf("put some characters to stdio.");
fgets(buffer,MAXLINE,stdin);
这两行代码在标准输出上打印一行字符,然后从标准输入读入一行到buffer中。如果按照上面的解释,那么在执行第二行代码的时候我们应该是看不到
put some characters to stdio.
这一行在屏幕上的输出的,因为这里的字符串并没有以换行符'\n'结尾,但是实际上程序是先输出
put some characters to stdio.
这一行到屏幕上的。

这里,要解释清楚这个问题,就必须提到关于行缓存的一条限制:任何时候只要是通过标准I/O库从一个无缓存的流,或者一个行缓存的流得到输入数据,那么标准I/O就会刷新所有行缓存的输出流。这个地方因为我们要从标准输入stdin得到输入数据,所以虽然标准输出stdout的缓存中还没装满数据,printf也仍然会将putsome characters to stdio.这一行输出到屏幕上。默认情况下,SVR4和4.4BSD使用下列类型的缓存:
 (1)标准出错stderr是无缓存的,无论stderr是否重定向到文件;
 (2)和终端设备联系在一起的流是行缓存的;
 (3)其他流是全缓存的。

2.从流中读写一个字符:
下面这段代码取自《UNIX环境高级编程》第109页:
#include
int
main(void)
{
 char c;
 while ((c = getchar()) != EOF)
  putchar(c);
 return 0;
}
这段代码在有的机器上运行正确,而其另外的机器上运行时会出错,R. Stevens给出的解释是:
getc(),fgetc(),getchar()在中的函数原型分别是:
int getc(FILE*fp); (注:getc()实际上是宏定义)
int fgetc(FILE *fp);
int getchar(void);
它们的返回值都是整型而非字符型,而文件结束标志EOF的通常定义为-1,如果系统使用的是有符号的字符型数据,那么程序可以正常工作;但是如果系统使用的是无符号的字符类型,那么返回的EOF保存到字符类型中之后已经不是-1了,因此程序将会出错,陷入死循环。我依稀地记得在谭老爷子的那本《C程序设计》上看到过类似的代码,所以在这里说一下。另外,无论是出错还是到达文件尾,这三个函数都返回EOF,因此必须调用ferror()或者feof()来对这两种情况进行区分。

3.打开流的限制:
我们可以像这样打开一个流:
if ((fp = fopen("filename","r+")) != NULL)
//打开流成功
}
这里的"r+",或者"w+",或者"a+"都是表明我们即可以对流读,也可以对流写,但是,这是有限制的:
 (1)如果在输出操作之后没有调用fflush(),fseek(),fsetpos(),或者rewind(),那么是不能在输出之后直接对流进行输入操作的;
 (2)如果在输入操作之后没有调用fseek(),fsetpos(),或者rewind(),或者当一个输出操作没有到达文件尾的时候,是不能在之后直接跟随输出操作的。
我猜想可能的原因是这样的,标准I/O的输入和输出操作使用的是同一缓冲区,所以必须先刷新缓冲区然后才能进行随后的操作。

个人意见,仅供参考。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值