APUE学习笔记——标准I/O

  今天我们围绕标准I/O做一些详细的讨论。
  首先,我们先来看一些重要的概念。

流和文件指针

  文件I/O操作都是针对文件描述符进行的,相对的,标准I/O的操作都是围绕一种叫做流(stream)的东西进行的,当使用标准 I/O 库打开或创建一个文件时,我们就已使一个流与这个文件相关联,通过流的读入和输出完成所需要的 I/O操作。
  用fopen打开一个流会返回一个指向FILE对象的指针,即文件指针,FILE对象通常是一个结构,包含了标准I/O库为管理该流需要的所有信息,如用于实际I/O的文件描述符、指向用于该流缓冲区的指针、缓冲区长度、出错标志等。
  系统为每个进程预定义了3个可以自动被使用的流:标准输入、标准输出和标准错误,这3个标准I/O流通过预定义的文件指针stdin、stdout、stderr加以引用。

缓冲

  标准I/O库提供缓冲的目的是尽可能减少使用read和write系统调用的次数,缓冲类型有三种:
  (1)全缓冲:填满标准I/O缓冲区后才进行实际I/O操作,磁盘中的文件通常是全缓冲,术语冲洗(flush)说明标准I/O缓冲区的写操作。
  (2)行缓冲:在输入和输出中遇到换行符或行缓冲区被填满时执行实际I/O操作,当流涉及一个终端(如标准输入和标准输出)时,通常使用行缓冲。
  (3)不带缓冲:标准I/O不对字符进行缓冲存储,标准错误stderr通常默认为不带缓冲的。
ISO C规定
  当且仅当stdin和stdout不指向交互式设备时,他们才是全缓冲。
  stderr决不会是全缓冲。

Linux系统默认
  stderr是不带缓冲的。
  若流指向终端设备,则是行缓冲,否则为全缓冲。
  
  对于一个给定的已经打开且尚未执行任何操作的流,我们可以调用setbuf和setvbuf来更改系统默认的缓冲类型。

#include <stdio.h>
void setbuf(FILE *restrict fp, char *restrict buf);
int setvbuf(FILE *restrict fp, char *restrict buf, int mode, size_t size);

               /*返回值:若成功。返回0;若出错,返回非0*/

  我们来看一下这两个函数的区别:
  setbuf只提供两种功能——打开或关闭由第一个参数fp指定的流的缓冲机制。若为打开缓冲,第二个参数buf必须指向一个长度为BUFSIZ的缓冲区,BUFSIZ定义在stdio.h中,至于调用函数之后究竟是全缓冲还是行缓冲,那就取决于该流是与终端相关还是与文件相关了;若想关闭该流的缓冲,只需把buf设为NULL即可。
  setvbuf功能就要强大一些,它多了两个参数mode和size,不仅可以实现setbuf的功能,还可以在打开缓冲时由mode指定具体的指定缓冲类型,由size指定缓冲区的长度。

mode参数 缓冲类型
_IOFBF 全缓冲
_IOLBF 行缓冲
_IONBF 不带缓冲

  关于这两个函数更详细的动作,可以看下下面这张表,这里就不再多费口舌了。
  这里写图片描述
关键字restrict:
  大家可能都注意到了,这两个函数的参数中都带有restrict这个关键字,查了下发现是C99新增的,它只用于限定指针,作用是告诉编译器,所有修改该指针所指向内容的操作都必须通过该指针进行,而不能通过其它途径(其它变量或指针)来修改。这样做的好处是能帮助编译器进行更好的代码优化,生成更有效率的汇编代码。
  


  接下来

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值