缓冲区的分类
- 行缓存:和终端文件相关的缓冲区叫做行缓存,行缓冲区的大小为1024字节,对应的文件指
针:stdin
、stdout
- 全缓存:和外界文件相关的缓冲区叫做全缓存,全缓冲区的大小为4096字节,对应的文件指
针:fp
- 不缓存:和标准出错相关的缓冲区叫不缓存,不缓存的大小为0字节,对应的文件指针:
stderr
验证过程:
#include<stdio.h>
#include<iostream>
using namespace std;
int main(int argc, const char *argv[])
{
//如果缓冲区没有被使用,则大小为0
//只有被至少使用一次后,缓冲区的大小就确定了
//1.可以通过两个方式求出行缓存的大小:1024
//标准输出
printf("行缓存的大小为:%d\n", stdout->_IO_buf_end - stdout->_IO_buf_base); //0
//看似没使用,实际上打印文字也算使用
printf("行缓存的大小为:%d\n", stdout->_IO_buf_end - stdout->_IO_buf_base); //1024
//标准输入
printf("行缓存的大小为:%d\n", stdin->_IO_buf_end - stdin->_IO_buf_base); //0
int num = 0;
//两种输入都可以
//scanf("%d", &num);//C
cin >> num;//C++
printf("行缓存的大小为:%d\n", stdin->_IO_buf_end - stdin->_IO_buf_base); //1024
//2.验证全缓存的大小为4096
FILE *fp = NULL;
if((fp = fopen("./ff.txt","r")) == NULL)
{
perror("fopen error");
return -1;
}
//未使用时
printf("全缓存的大小为:%d\n", fp->_IO_buf_end - fp->_IO_buf_base); //0
//使用一次全缓存
fgetc(fp);
printf("全缓存的大小为:%d\n", fp->_IO_buf_end - fp->_IO_buf_base); //4096
//3.验证不缓存的大小为0
//未使用时
printf("不缓存的大小为:%d\n", stderr->_IO_buf_end - stderr->_IO_buf_base); //0
//使用一次不缓存
perror("test error");
printf("不缓存的大小为:%d\n", stderr->_IO_buf_end - stderr->_IO_buf_base); //0
return 0;
}
验证结果:
缓冲区的刷新时机
对于三种缓冲区,都可以使用缓冲区刷新函数fflush
来手动刷新。
#include <stdio.h>
/*
功能:刷新给定的文件指针对应的缓冲区
参数:文件指针
返回值:成功返回0,失败返回EOF并置位错误码
*/
int fflush(FILE *stream);
除了手动刷新,遇到以下情况缓冲区也会自动刷新:
- 行缓存
- 当程序结束后
- 当遇到换行时
- 当输入输出发生切换时
- 当关闭行缓存对应的文件指针时
- 当缓冲区满了后(行缓存大小:1024字节)
示例:
#include<stdio.h>
#include<iostream>
using namespace std;
int main(int argc, const char *argv[])
{
//1.当程序结束后
printf("hello");
return 0;
//2.当遇到换行时
printf("hello\n");
while(1);//防止程序结束
//3.当输入输出发生切换时
int num = 0;
printf("请输入:");
scanf("%d", &num);
//4.当关闭行缓存对应的文件指针(stdin stdout stderr)时
printf("hello");
fclose(stdout);
while(1);//防止程序结束
//5.当缓冲区满了后(行缓存大小:1024字节)
for(int i = 0; i < 1025; i++)
{
printf("A");
}
while(1); //防止程序结束
return 0;
}
- 全缓存
- 当程序结束后
- 当输入输出发生切换时
- 当关闭缓冲区对应的文件指针时
- 当缓冲区满了后(全缓存大小:4096字节)
示例:
#include<iostream>
#include<stdio.h>
using namespace std;
int main(int argc, const char *argv[])
{
//打开一个文件
FILE *fp = NULL;
if((fp = fopen("./aa.txt", "r+")) == NULL) //以读写的形式打开文件
{
perror("fopen error");
return -1;
}
//1.当程序结束后
fputs("hello world!\n", fp);
return 0;
//2.当输入输出发生切换时
fputs("I love China\n", fp); //向文件中输出一个字符串
fgetc(fp); //从文件中读取一个字符,主要是让输入输出发生切换
while(1);
//3.当关闭缓冲区对应的文件指针时
fputs("北京欢迎你", fp);
fclose(fp); //刷新文件指针
while(1);
//4.当缓冲区满了后(全缓存大小:4096字节)
for(int i = 0; i < 4097; i++)
{
fputc('A', fp); //循环将单字符放入文件中
}
while(1); //防止程序结束
return 0;
}
- 不缓存
1.只要放入数据就会刷新缓冲区
示例:
#include<iostream>
#include<stdio.h>
using namespace std;
int main(int argc, const char *argv[])
{
//perror("a");
//向标准出错中放入数据
fputs("A", stderr); //向标准出错缓冲区中写入一个字符A
while(1); //阻塞
return 0;
}