时间:2021-05-20
1.简介
C/C++中,基于I/O流的操作最终会调用系统接口read()和write()完成I/O操作。为了使程序的运行效率最高,流对象通常会提供缓冲区,以减少调用系统I/O接口的调用次数。
缓冲方式存在三种,分别是:
(1)全缓冲。输入或输出缓冲区被填满,会进行实际I/O操作。其他情况,如强制刷新、进程结束也会进行实际I/O操作。
对于读操作来说,当读入内容的字节数等于缓冲区大小或者文件已经到达结尾,或者强制刷新,会进行实际的I/O操作,将外存文件内容读入缓冲区;对于写操作来说,当缓冲区被填满或者强制刷新,会进行实际的I/O操作,缓冲区内容写到外存文件中。磁盘文件操作通常是全缓冲的。
(2)行缓冲。输入或输出缓冲区遇到换行符会进行实际I/O操作。其他与全缓冲相同。
(3)无缓冲。没有缓冲区,数据会立即读入内存或者输出到外存文件和设备上。标准错误输出stderr是无缓冲的,这样能够保证错误信息及时反馈给用户,供用户排除错误。
三种缓冲类型的宏定义在头文件<stdio.h>。
缓冲类型 宏 全缓冲 _IOFBF 行缓冲 _IOLBF 无缓冲 _IONBFLinux环境下,下面一段代码可以很好地体现全缓冲和行缓冲的区别。
#include <stdio.h>#include <stdlib.h>int glob=6; int main(int argc, char** argv){ int var; pid_t pid; printf("a write to stdout\n"); if(pid=fork()<0) { printf("fork error"); } else { if(pid==0) { glob++; var++; } else { sleep(2); } } printf("pid=%d,glob=%d,var=%d\n",getpid(),glob,var); exit(0); }编译成功后默认生成a.out,运行结果如下:
./a.out
a write to stdout
pid=4823,glob=7,var=4195873
pid=4824,glob=7,var=4195873
./a.out > temp.txt
cat temp.txt
a write to stdout
pid=4864,glob=7,var=4195873
a write to stdout
pid=4865,glob=7,var=4195873
可见printf在输出到标准输出(显示器)时,是行缓冲,遇到换行符时会将缓冲区内容输出到显示器,并清空缓冲区。当使用重定向命令时,标准输出被重定向到磁盘文件,此时标准输出变成全缓冲,遇到换行符不输出,而是被拷贝至子进程中,在父子进程结束后,各有一份输出。
2.缓冲区的设置
(1)缓冲打开或关闭,可使用函数setbuf()或者setbuffer()。参数buf指向缓冲区,表示开启缓冲,通常是全缓冲。将buf参数设置为NULL,表示关闭缓冲。注意,setbuffer()是非C标准库函数,常见于Linux。
setbuf()的缓冲区长度至少为BUFSIZ(定义在stdio.h),否则可能会出现缓冲区溢出。setbuffer可以指定缓冲区大小。
//@header:stdio.h//@brief:设置指定的缓冲区或关闭缓冲//@param:stream:文件指针;buffer:缓冲区地址//@notice:使用默认缓冲大小BUFSIZ(在stdio.h中定义)void setbuf ( FILE * stream, char * buffer );//@notice:同setbuf,但可指定缓冲区大小void setbuffer(FILE *stream, char *buf, size_t size);将buffer指定为NULL,关闭标准输出缓冲。
setbuf(stdout,NULL)指定新的缓冲区。
static char newBuffer[BUFSIZ];//至少是BUFSIZ(定义在stdio.h),否则存在缓冲溢出可能setbuf(stdout,(char*)&newBuffer);//或者指定缓冲区大小static char newBuffer[512];setbuffer(stdout,(char*)&newBuffer,512);(2)更改缓冲模式,可使用函数setvbuf()。
//@header:stdio.h//@brief:更改缓冲模式并设置缓冲区//@param:stream:文件指针;buf缓冲区地址;type:缓冲区模式;size:缓冲区大小//@ret:0成功,非0失败int setvbuf(FILE *stream, char *buf, int type, unsigned size);例如,将流缓冲区设置为行缓冲,调用setvbuf()时,缓冲区地址设为NULL,缓冲区大小设为0。注意,前提是存在缓冲区。
setvbuf(stream,NULL,_IOLBF,0); //将缓冲改为行缓冲//上面的代码等价于setlinebuf(stream); //for Linux如果调用setvbuf指定了缓冲区大小size大于0,缓冲区buf为NULL,则交由setvbuf进行malloc申请缓冲区。
//间接申请1024字节全缓冲区setvbuf(stream,NULL,_IOFBF,1024);以上就是C/C++的全缓冲、行缓冲和无缓冲的详细内容,更多关于C/C++ 缓冲的资料请关注其它相关文章!
声明:本页内容来源网络,仅供用户参考;我单位不保证亦不表示资料全面及准确无误,也不保证亦不表示这些资料为最新信息,如因任何原因,本网内容或者用户因倚赖本网内容造成任何损失或损害,我单位将不会负任何法律责任。如涉及版权问题,请提交至online#300.cn邮箱联系删除。
文件的io操作的缓冲行为分为全缓冲:同系统及磁盘块大小有关,n个字节后执行一次写入操作行缓冲:遇到换行符执行一次写操作无缓冲:立刻执行写操作open()函数he
前言C++输入过程中,是把输入加载到缓冲区中,然后对缓冲区中的字符进行读取。cin,cin.get(),cin.getline()三个函数虽然都可以进行舒服读取
关于缓冲查询和无缓冲查询MySQL的客户端有两种类型的查询:缓冲查询:将接收查询的结果并把他们存储在客户端的缓存中,而且接下来获取行记录的请求仅仅从本地内获取。
C语言setbuf()函数:把缓冲区与流相关联头文件:#include函数setbuf()用于将指定缓冲区与特定的文件流相关联,实现操作缓冲区时直接操作文件流的
c++换行符有哪些\n换行,光标移到下一行的开头;endl,把缓冲槽的内容输出到控制台;\r回车,光标移到当前行的开头,不会换到下一行,如果接着输出的话,本行以