C/C++的全緩沖、行緩沖和無緩沖
1.簡介
C/C++中,基于I/O流的操作最終會調(diào)用系統(tǒng)接口read()和write()完成I/O操作。為了使程序的運行效率最高,流對象通常會提供緩沖區(qū),以減少調(diào)用系統(tǒng)I/O接口的調(diào)用次數(shù)。
緩沖方式存在三種,分別是:
(1)全緩沖。輸入或輸出緩沖區(qū)被填滿,會進行實際I/O操作。其他情況,如強制刷新、進程結(jié)束也會進行實際I/O操作。
對于讀操作來說,當(dāng)讀入內(nèi)容的字節(jié)數(shù)等于緩沖區(qū)大小或者文件已經(jīng)到達結(jié)尾,或者強制刷新,會進行實際的I/O操作,將外存文件內(nèi)容讀入緩沖區(qū);對于寫操作來說,當(dāng)緩沖區(qū)被填滿或者強制刷新,會進行實際的I/O操作,緩沖區(qū)內(nèi)容寫到外存文件中。磁盤文件操作通常是全緩沖的。
(2)行緩沖。輸入或輸出緩沖區(qū)遇到換行符會進行實際I/O操作。其他與全緩沖相同。
(3)無緩沖。沒有緩沖區(qū),數(shù)據(jù)會立即讀入內(nèi)存或者輸出到外存文件和設(shè)備上。標(biāo)準(zhǔn)錯誤輸出stderr是無緩沖的,這樣能夠保證錯誤信息及時反饋給用戶,供用戶排除錯誤。
三種緩沖類型的宏定義在頭文件<stdio.h>。
| 緩沖類型 | 宏 |
| 全緩沖 | _IOFBF |
| 行緩沖 | _IOLBF |
| 無緩沖 | _IONBF |
Linux環(huán)境下,下面一段代碼可以很好地體現(xiàn)全緩沖和行緩沖的區(qū)別。
#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);
}
編譯成功后默認(rèn)生成a.out,運行結(jié)果如下:
./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在輸出到標(biāo)準(zhǔn)輸出(顯示器)時,是行緩沖,遇到換行符時會將緩沖區(qū)內(nèi)容輸出到顯示器,并清空緩沖區(qū)。當(dāng)使用重定向命令時,標(biāo)準(zhǔn)輸出被重定向到磁盤文件,此時標(biāo)準(zhǔn)輸出變成全緩沖,遇到換行符不輸出,而是被拷貝至子進程中,在父子進程結(jié)束后,各有一份輸出。
2.緩沖區(qū)的設(shè)置
(1)緩沖打開或關(guān)閉,可使用函數(shù)setbuf()或者setbuffer()。參數(shù)buf指向緩沖區(qū),表示開啟緩沖,通常是全緩沖。將buf參數(shù)設(shè)置為NULL,表示關(guān)閉緩沖。注意,setbuffer()是非C標(biāo)準(zhǔn)庫函數(shù),常見于Linux。
setbuf()的緩沖區(qū)長度至少為BUFSIZ(定義在stdio.h),否則可能會出現(xiàn)緩沖區(qū)溢出。setbuffer可以指定緩沖區(qū)大小。
//@header:stdio.h //@brief:設(shè)置指定的緩沖區(qū)或關(guān)閉緩沖 //@param:stream:文件指針;buffer:緩沖區(qū)地址 //@notice:使用默認(rèn)緩沖大小BUFSIZ(在stdio.h中定義) void setbuf ( FILE * stream, char * buffer ); //@notice:同setbuf,但可指定緩沖區(qū)大小 void setbuffer(FILE *stream, char *buf, size_t size);
將buffer指定為NULL,關(guān)閉標(biāo)準(zhǔn)輸出緩沖。
setbuf(stdout,NULL)
指定新的緩沖區(qū)。
static char newBuffer[BUFSIZ];//至少是BUFSIZ(定義在stdio.h),否則存在緩沖溢出可能 setbuf(stdout,(char*)&newBuffer); //或者指定緩沖區(qū)大小 static char newBuffer[512]; setbuffer(stdout,(char*)&newBuffer,512);
(2)更改緩沖模式,可使用函數(shù)setvbuf()。
//@header:stdio.h //@brief:更改緩沖模式并設(shè)置緩沖區(qū) //@param:stream:文件指針;buf緩沖區(qū)地址;type:緩沖區(qū)模式;size:緩沖區(qū)大小 //@ret:0成功,非0失敗 int setvbuf(FILE *stream, char *buf, int type, unsigned size);
例如,將流緩沖區(qū)設(shè)置為行緩沖,調(diào)用setvbuf()時,緩沖區(qū)地址設(shè)為NULL,緩沖區(qū)大小設(shè)為0。注意,前提是存在緩沖區(qū)。
setvbuf(stream,NULL,_IOLBF,0); //將緩沖改為行緩沖 //上面的代碼等價于 setlinebuf(stream); //for Linux
如果調(diào)用setvbuf指定了緩沖區(qū)大小size大于0,緩沖區(qū)buf為NULL,則交由setvbuf進行malloc申請緩沖區(qū)。
//間接申請1024字節(jié)全緩沖區(qū) setvbuf(stream,NULL,_IOFBF,1024);
以上就是C/C++的全緩沖、行緩沖和無緩沖的詳細內(nèi)容,更多關(guān)于C/C++ 緩沖的資料請關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
C語言熱門考點結(jié)構(gòu)體與內(nèi)存對齊詳解
在掌握基本的結(jié)構(gòu)體使用后,我們在面試和大型比賽中常常會遇到一個熱門考點:結(jié)構(gòu)體內(nèi)存對齊,也就是計算結(jié)構(gòu)體大小。接下來請跟著筆者一起來學(xué)習(xí)這塊知識點吧2021-10-10
C++ 標(biāo)準(zhǔn)庫中的 <algorithm> 頭文件算法操作總結(jié)
C++ 標(biāo)準(zhǔn)庫中的 <algorithm> 頭文件提供了大量有用的算法,主要用于操作容器(如 vector, list, array 等),這些算法通常通過迭代器來操作容器元素,本文給大家介紹C++ 標(biāo)準(zhǔn)庫中的 <algorithm> 頭文件算法總結(jié),感興趣的朋友一起看看吧2025-04-04
C++自帶的sort函數(shù)如何對vector容器元素進行排序
這篇文章主要介紹了C++自帶的sort函數(shù)如何對vector容器元素進行排序問題,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教2023-10-10
VSCode下.json文件的編寫之(1) linux/g++ (2).json中參數(shù)與預(yù)定義變量的意義解釋
這篇文章主要介紹了VSCode下.json文件的編寫之(1) linux/g++ (2).json中參數(shù)與預(yù)定義變量的意義解釋,本文給大家介紹的非常詳細,對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下2020-03-03
在輸入輸出字符串時scanf(),printf()和gets(),puts()的區(qū)別淺談
在輸入輸出字符串時scanf(),printf()和gets(),puts()的區(qū)別淺談,需要的朋友可以參考一下2013-02-02

