浅析C标准I/O库

1. 概述
      标准I/O库由ISO C标准说明,其与POSIX定义的文件I/O具有明显区别。标准I/O库是围绕流进行的,而POSIX定义的文件I/O则是针对文件描述符的。

2. 缓冲区
标准I/O 会对用户的I/O操作进行缓冲,共分为全缓冲、行缓冲及不缓冲三种。
      全缓冲:直到用户定义的缓冲区被填满,才会调用系统I/O函数。
      行缓冲:在缓冲区(一般大小为1024)被填满或者遇到换行符'/n’时才调用系统I/O函数
      无缓冲:没有缓冲区,立即调用系统I/O函数。

ISO C要求下列缓冲特征:
     a. 当且仅当标准输入和标准输出并不涉及交互作用设备时,它们才是全缓存的。
     b. 标准出错决不会是全缓冲的
    但是,这并没有告诉我们如果标准输入和输出涉及交互作用设备时,它们是不带缓存的还是行缓存的,以及标准输出是不带缓存的,还是行缓存的。

很多系统默认使用下列类型的缓冲:
     a. 标准出错是不带缓冲的。
     b. 如若是涉及终端设备的其他流,则它们是行缓冲的;否则是全缓冲的。

     需要注意的是,这里的缓冲区是指用户空间的缓冲区。我们常常说系统调用read、write、open、close是unbuffered I/O,但是,write的底层也可以分配内核缓冲区。

3. FILE结构体
标准I/O 通过fopen会返回一个指向FILE的指针,FILE结构内容如下:

   1: typedef struct _IO_FILE FILE;
   2: 
   3: struct _IO_FILE {
   4:   int _flags;           /* High-order word is _IO_MAGIC; rest is flags. */
   5: #define _IO_file_flags _flags
   6: 
   7:   /* The following pointers correspond to the C++ streambuf protocol. */
   8:   /* Note:  Tk uses the _IO_read_ptr and _IO_read_end fields directly. */
   9:   char* _IO_read_ptr;   /* Current read pointer */
  10:   char* _IO_read_end;   /* End of get area. */
  11:   char* _IO_read_base;  /* Start of putback+get area. */
  12:   char* _IO_write_base; /* Start of put area. */
  13:   char* _IO_write_ptr;  /* Current put pointer. */
  14:   char* _IO_write_end;  /* End of put area. */
  15:   char* _IO_buf_base;   /* Start of reserve area. */
  16:   char* _IO_buf_end;    /* End of reserve area. */
  17:   /* The following fields are used to support backing up and undo. */
  18:   char *_IO_save_base; /* Pointer to start of non-current get area. */
  19:   char *_IO_backup_base;  /* Pointer to first valid character of backup area */
  20:   char *_IO_save_end; /* Pointer to end of non-current get area. */
  21: 
  22:   struct _IO_marker *_markers;
  23: 
  24:   struct _IO_FILE *_chain;
  25:   int _fileno;
  26: #if 0
  27:   int _blksize;
  28: #else
  29:   int _flags2;
  30: #endif
  31:   _IO_off_t _old_offset; /* This used to be _offset but it's too small.  */
  32: 
  33: #define __HAVE_COLUMN /* temporary */
  34:   /* 1+column number of pbase(); 0 is unknown. */
  35:   unsigned short _cur_column;
  36:   signed char _vtable_offset;
  37:   char _shortbuf[1];
  38: 
  39:   /*  char* _save_gptr;  char* _save_egptr; */
  40: 
  41:   _IO_lock_t *_lock;
  42: #ifdef _IO_USE_OLD_IO_FILE
  43: };

       标准库函数都是通过对FILE的操作来实现读写文件的目的。
       
4. 标准输入、标准输出和标准出错
对进程,系统预定义了上述三个流,并且这三个流可以自动地被进程使用,这三个流通过预定义文件指针:stdin、stdout、stderr加以引用。
      我们可以查看其缓冲区属性,程序如下:

   1: //输出FILE属性
   2: void streaming_property(FILE* file)
   3: {
   4:         //输出FILE缓冲区类型
   5:         if(file->_flags & _IO_UNBUFFERED)
   6:                 printf("unbuffered/n");
   7:         else if(file->_flags & _IO_LINE_BUF)
   8:                 printf("line-buffered/n");
   9:         else
  10:                 printf("fully-buffered/n");
  11: 
  12:         //输出缓冲区大小
  13:         printf("buffer size is %d/n", file->_IO_buf_end -
  14:                                 file->_IO_buf_base);
  15: 
  16:         //输出discriptor值
  17:         printf("discriptor is %d/n/n", fileno(file));
  18: }
  19: 
  20: 
  21: int main(int argc, char** argv)
  22: {
  23:     printf("stdin is ");
  24:     streaming_property(stdin);
  25: 
  26:     printf("stdout is ");
  27:     streaming_property(stdout);
  28: 
  29:     printf("stderr is ");
  30:     streaming_property(stderr);
  31: }

 输出:

   1: stdin is fully-buffered
   2: buffer size is 0
   3: discriptor is 0
   4: 
   5: stdout is line-buffered
   6: buffer size is 1024
   7: discriptor is 1
   8: 
   9: stderr is unbuffered
  10: buffer size is 0
  11: discriptor is 2

5. 常用的标准库函数
    更改缓冲类型:setbuf/setvbuf
    流的打开和关闭: fopen/fclose
    单字符输入: getc/fgetc/getchar
    流的错误处理: ferror/feof/clearerr
    返还字符: ungetc
    单字符输出: putc/fputc/putchar
    行输入: gets/fgets
    行输出: puts/fputs
    二进制读写: fwrite/fread
    流的定位: ftell/fseek/rewind/fgetpos/fsetpos
    格式化输出: printf/fprintf/sprintf
    格式化输入: scanf/fscanf/sscanf

参考文献

1. apue第二版
2. http://hi.chinaunix.net/?uid-20693307-action-viewspace-itemid-46724

转载于:https://my.oschina.net/zipu888/blog/549716

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值