阅读目录

  • 概念
  • 缓冲区类型
    • 1. 全缓冲
    • 2. 行缓冲
    • 3. 不带缓冲
  • 缓冲区特征
    • 1. 缓存特征
    • 2. 缓冲区的大小
    • 3. 缓冲区的刷新(清空)
    • 4. 缓冲类型和大小确认函数
  • 缓冲实例
  • FILE结构定义
  • 参考资料

概念

缓冲区又称为缓存,它是内存空间的一部分。也就是说,在内存空间中预留了一定的存储空间,这些存储空间用来缓冲输入或输出的数据,这部分预留的空间就叫做缓冲区。

缓冲区根据其对应的是输入设备还是输出设备,分为输入缓冲区和输出缓冲区。

为什么要引入缓冲区
比如我们从磁盘里取信息,我们先把读出的数据放在缓冲区,计算机再直接从缓冲区中取数据,等缓冲区的数据取完后再去磁盘中读取,这样就可以减少磁盘的读写次数,再加上计算机对缓冲区的操作大大快于对磁盘的操作,故应用缓冲区可大大提高计算机的运行速度。

又比如,我们使用打印机打印文档,由于打印机的打印速度相对较慢,我们先把文档输出到打印机相应的缓冲区,打印机再自行逐步打印,这时我们的CPU可以处理别的事情。

现在您基本明白了吧,缓冲区就是一块内存区,它用在输入输出设备和CPU之间,用来缓存数据。它使得低速的输入输出设备和高速的CPU能够协调工作,避免低速的输入输出设备占用CPU,解放出CPU,使其能够高效率工作。

缓冲区类型

缓冲区 分为三种类型:全缓冲、行缓冲和不带缓冲。

1. 全缓冲

在这种情况下,当填满标准I/O缓存后才进行实际I/O操作。全缓冲的典型代表是对磁盘文件的读写。

一般磁盘文件是全缓冲的(缓冲区一般为4096个字节)。

2. 行缓冲

在这种情况下,当在输入和输出中遇到换行符时,执行真正的I/O操作。这时,我们输入的字符先存放在缓冲区,等按下回车键换行时才进行实际的I/O操作。典型代表是标准输入(stdin)和标准输出(stdout)。

注意:换行符也被读入缓冲区。(缓冲区一般为1024个字节)

3. 不带缓冲

也就是不进行缓冲,标准出错情况stderr是典型代表,这使得出错信息可以直接尽快地显示出来。

缓冲区特征

1. 缓存特征

ANSI C( C89 )要求缓存具有下列特征:
当且仅当标准输入和标准输出并不涉及交互设备时,它们才是全缓存的。
标准出错决不会是全缓存的。

但是,这并没有告诉我们如果标准输入和输出涉及交互作用设备时,它们是不带缓存的还是行缓存的,以及标准输出是不带缓存的,还是行缓存的。

大部分系统默认使用下列类型的缓存:
标准出错是不带缓存的。
如果是涉及终端设备的流,则它们是行缓存的;否则是全缓存的。

我们经常要用到标准输入输出流,而ANSI C对stdin、stdout和stderr的缓存特征没有强行的规定,以至于不同的系统可能有不同的stdin、stdout和stderr的缓存特征。目前主要的缓存特征是:stdin和stdout是行缓存;而stderr是无缓存的。

2. 缓冲区的大小

如果我们没有自己设置缓冲区的话,系统会默认为标准输入输出设置一个缓冲区,这个缓冲区的大小通常是4096个字节的大小,这和计算机中的分页机制有关,因为进程在计算机中分配内存使用的就是分页与分段的机制,并且每个页的大小是4096个字节,因此通常情况下缓冲区的大小会设置为4096个字节的大小。

缓冲区大小由stdio.h头文件中的宏BUFSIZ定义,如果希望查看它的大小,包含头文件,直接输出它的值即可。

#include <stdio.h>int main()
{printf("<stdio.h> BUFSIZ:%d\n",BUFSIZ);return 0;
}

缓冲区的大小是可以改变的,也可以将文件关联到自定义的缓冲区,详情可以查看setbug()和setvbuf()函数。
https://www.runoob.com/cprogramming/c-function-setbuf.html
https://www.runoob.com/cprogramming/c-function-setvbuf.html

3. 缓冲区的刷新(清空)

下列情况会引发缓冲区的刷新:
缓冲区满时;
行缓冲区遇到回车时;
关闭文件;
使用特定函数刷新缓冲区,如fflush()函数

我们上面提到标准输入输出是行缓冲,即一行满了才会刷新,那什么是刷新呢?刷新就是将数据从缓冲区取出来,真正能刷新,要满足什么条件呢?

1、满刷新,即一行满了(1024个字节)才会刷新;

2、遇到’\n’会刷新;

3、调用fflush()函数;

4、程序结束 fclose();

4. 缓冲类型和大小确认函数

//这是一个分别打印三个标准流和一个文件流的缓冲方式的应用实例
#include <stdio.h>
#include <stdlib.h>#if defined(MACOS)
#define _IO_UNBUFFERED  __SNBF
#define _IO_LINE_BUF    __SLBF
#define _IO_file_flags  _flags
#define BUFFERSZ(fp)    (fp)->_bf._size
#else
#define BUFFERSZ(fp)    ((fp)->_IO_buf_end - (fp)->_IO_buf_base)
#endif
//以上是关于缓冲方式和缓冲区大小的预定义
void pr_stdio(const char *, FILE *);
//子函数声明
int main(int argc,char *argv[])
{FILE  *fp = NULL;   //流文件结构指针pr_stdio("stdin",  stdin);    //标准输入pr_stdio("stdout", stdout);   //标准输出pr_stdio("stderr", stderr);   //标准出错处理printf("fopen error\n");fp = fopen("file.txt", "w+");fprintf(fp, "%s %s %s %d", "We", "are", "in", 2020);pr_stdio("file", fp);   //文件return 0;
}
//测试缓冲输出函数
void  pr_stdio(const char *name, FILE *fp)
{   printf("当前流是%s, ", name);   //打印流的名称if (fp->_IO_file_flags & _IO_UNBUFFERED){printf("无缓冲\n");}else if (fp->_IO_file_flags & _IO_LINE_BUF){printf("行缓冲\n");}else{ printf("全缓冲\n");}printf(", 缓冲区大小 = %ld\n", BUFFERSZ(fp));return;
}

https://blog.51cto.com/10638473/1983077

缓冲实例

我们以printf函数和stderr为例,先说明stdout(对应printf)是遇到换行符或缓冲区满之后或程序结束后才输出缓冲,stderr一般是无缓冲的:

/*
** 在我的实验环境中,缓冲区大小默认为1024
*/
#include <stdio.h>int main()
{while(1) {printf(".");fprintf(stderr, "1");}return 0;
}

运行结果:

(你可以数数,有1024个1,然后1024个’.’,…)
或者你可以通过用./a.out > t 2>&1重定向标准输出和错误到文件t中,这样就可以很容易看到运行结果(因为程序跑的很快,很难找到开始运行出来的那一行),这时的缓冲区大小是4096个字节。

FILE结构定义

头文件

<sys/reent.h> defines __FILE, _fpos_t.

默认定义

struct __sFILE {unsigned char *_p;   /* current position in (some) buffer */int  _r;     /* read space left for getc() */int _w;     /* write space left for putc() */short  _flags;     /* flags, below; this FILE is free if 0 */short _file;      /* fileno, if Unix descriptor, else -1 */struct __sbuf _bf; /* the buffer (at least 1 byte, if !NULL) */int _lbfsize;   /* 0 or -_bf._size, for inline putc */#ifdef _REENT_SMALLstruct _reent *_data;
#endif/* operations */_PTR  _cookie;    /* cookie passed to io functions */_READ_WRITE_RETURN_TYPE _EXFNPTR(_read, (struct _reent *, _PTR,char *, _READ_WRITE_BUFSIZE_TYPE));_READ_WRITE_RETURN_TYPE _EXFNPTR(_write, (struct _reent *, _PTR,const char *,_READ_WRITE_BUFSIZE_TYPE));_fpos_t _EXFNPTR(_seek, (struct _reent *, _PTR, _fpos_t, int));int _EXFNPTR(_close, (struct _reent *, _PTR));/* separate buffer for long sequences of ungetc() */struct __sbuf _ub;    /* ungetc buffer */unsigned char *_up;  /* saved _p when _p is doing ungetc data */int  _ur;        /* saved _r when _r is counting ungetc data *//* tricks to meet minimum requirements even when malloc() fails */unsigned char _ubuf[3]; /* guarantee an ungetc() buffer */unsigned char _nbuf[1];   /* guarantee a getc() buffer *//* separate buffer for fgetline() when line crosses buffer boundary */struct __sbuf _lb; /* buffer for fgetline() *//* Unix stdio files get aligned to block boundaries on fseek() */int _blksize;   /* stat.st_blksize (may be != _bf._size) */_off_t _offset; /* current lseek offset */#ifndef _REENT_SMALLstruct _reent *_data; /* Here for binary compatibility? Remove? */
#endif#ifndef __SINGLE_THREAD___flock_t _lock;  /* for thread-safety locking */
#endif_mbstate_t _mbstate;  /* for wide char stdio functions. */int   _flags2;        /* for future use */
};

参考资料

https://www.cnblogs.com/pricks/p/3821832.html
https://www.cnblogs.com/mydomain/p/9817320.html
https://blog.csdn.net/snowlyw/article/details/80963494

C语言标准输入输出缓冲区相关推荐

  1. 为什么读写文件要有缓冲区?为什么要有输入输出缓冲区?

    有输入输出缓冲区用以暂时存放读写期间的文件数据而在内存区预留的一定空间.即利用主存的存储空间来暂存从磁盘中输入输出的信息.目的是缓和CPU 与 I/O 设备间速度不匹配的矛盾.减少对 CPU 的中断频 ...

  2. C/C 输入输出缓冲区

    [导读]:本文介绍C与C 输入输出缓冲的一些操作与特性. 以下是正文 (1)c 中cin.cout,cerr和c的stdin.stdout.stderr都是同步的,即iostream 对象和 and ...

  3. 5.1.6 假脱机技术(输入井、输出井、输入输出缓冲区、共享打印机原理分析)

    0. 知识总览 1. 什么是脱机技术? 2. 假脱机技术 2.1 输入井和输出井 2.2 输入进程与输出进程 2.3 输入输出缓冲区 3. 共享打印机原理分析 4. 知识回顾与重要考点 0. 知识总览 ...

  4. c语言怎么清空标准输入缓冲区,C语言中如何清空输入输出缓冲区

    C语言中如何清空输入输出缓冲区 答案:5  信息版本:手机版 解决时间 2019-10-06 09:40 已解决 2019-10-05 13:54 C语言中如何清空输入输出缓冲区 最佳答案 2019- ...

  5. 取代C语言标准输入输出:cin 和 cout【C++标准输入输出】

    C语言 和 C++ 标准输入输出的区别 cin标准输入 解决scanf输入字符的问题 解决C语言输入字符串的问题 cout 进制输出 域宽 左对齐 / 右对齐 填充 设置有效数字 设置浮点数精度 C语 ...

  6. c语言标准输入输出ppt,c语言输入输出语句PPT

    <c语言输入输出语句PPT>由会员分享,可在线阅读,更多相关<c语言输入输出语句PPT(29页珍藏版)>请在人人文库网上搜索. 1.输入输出语句通常需要在程序运行过程中输入数据 ...

  7. 详解,c/c++输入输出缓冲区,以及scanf回车的问题

    一.输出缓冲区 输出缓冲区是我们在dos窗口下,或终端下,linux/windows为我们分配的默认输出缓冲区大小,也就是窗口一次能容下多少字符!输出缓冲区大小是和图像一样的,用宽高来定义的,换句话说 ...

  8. c语言标准输入输出ppt,C语言版输入输出.ppt

    <C语言版输入输出.ppt>由会员分享,可在线阅读,更多相关<C语言版输入输出.ppt(25页珍藏版)>请在装配图网上搜索. 1.第二章 C语言版输入输出,C语言中的输入输出操 ...

  9. Redis 输入输出缓冲区解析

    Redis 缓冲区的用法 前言 一.客户端输入和输出缓冲区 1.结构组成 2.相关命令 3.注意事项 二.输出缓冲区溢出的应对方法 1.配置防范 2.操作注意 三.主从集群中的缓冲区 1.结构组成 2 ...

最新文章

  1. linux多线程求和_211渣硕,海投200+家Java岗(面40,过7),收获多份offer!
  2. 用Alpha生成Trimp图的方法(python)
  3. 用MFC制作程序启动logo
  4. 【机器学习】创建自己的电影推荐系统
  5. 剑指offer 数值的整次方
  6. React中ref的使用方法
  7. Visual Studio 2010 实用功能总结
  8. 程序开发入门工具之CodeBlocks
  9. 9个项目助你在2020年成为前端大师!
  10. mysql 连边聚合_MySQL分组,聚合函数,连表查询,子查询
  11. Spring Cloud (6)config 客户端配置 与GitHub通信
  12. 产品配件类目税目分类_商品及税收分类编码选择技巧
  13. sql里的正则表达式
  14. java程序员推荐app_Java程序员面试大全app
  15. 替代CATIA查看stp/step格式模型免费软件推荐
  16. sql查询日期格式化
  17. 图形学基础|景深效果(Depth of Field/DOF)
  18. java jive歌词翻译_Java Jive歌词 Java JiveLrc歌词
  19. Linux设备驱动之udal341声卡驱动与madplay播放器移植
  20. 实训任务04 MapReduce编程入门

热门文章

  1. 《Python程序设计与算法基础教程(第二版)》江红 余青松,第九章课后习题答案
  2. HQChart--uniApp v3 中使用 render.js
  3. 为什么go语言还没有火起来?go语言有哪些劣势?
  4. MATLAB编程-弹簧振动动画
  5. 用python画枫叶-Python中的用for,while循环遍历文件实例
  6. css实现渐变图片——曲线救国解决笔记
  7. 第11篇- 抓取免费代理IP并搭建自己的代理IP池
  8. 关于Redux到底是个什么鬼
  9. 现阶段为什么国内程序员无法很好的参与到开源社区?
  10. 测试用例设计 通用原则