緩衝模式與 fflush
/ fflush -> EFF-flush /
那個水桶究竟什麼時候才真的被倒進屋裡?stdio 串流把你的位元組收集在緩衝區裡,但你得知道它何時把那個緩衝區倒給核心的規則。規則有三種,稱為緩衝模式,外加一個你可以自己按下、強迫立刻傾倒的按鈕。
三種模式是:全緩衝,位元組累積到緩衝區滿了(通常幾 KiB)才寫出去——這是一般檔案的預設,因為它把效率最大化;行緩衝,每寫入一個換行就清出緩衝區一次——這是 stdout 接到終端機時通常的預設,所以你能在每一行印出時就看到它;無緩衝,每次寫入都立即直接通過——這是 stderr 的預設,好讓程式當掉時錯誤訊息絕不會被困在緩衝區後面。你可以在開啟後立刻用 setvbuf() 自行設定模式。手動覆寫鈕是 fflush(stream):它強迫該串流緩衝區裡目前的東西一次全部送往核心。fflush(NULL) 會清出每一個輸出串流。注意:flush 把資料從 stdio 緩衝區推進核心;它不保證資料已在實體磁碟上——那需要描述符層級的 fsync()。
為何重要:這是初學者最常見的單一困惑。一個 printf("working...") 不帶換行、接著跑一個長迴圈的程式,可能在螢幕上什麼都不顯示,因為那一行從未被清出——工作正在進行,訊息只是卡在緩衝區裡。呼叫 fflush(stdout) 就能修好它。同樣的緩衝意味著:若程式當掉,未清出的輸出就丟失了。知道每個串流的模式,並在時機重要時伸手去拿 fflush,就能把「為什麼什麼都沒印出來?」變成一點都不神秘的事。
printf("working..."); /* 沒有換行:可能卡在緩衝區裡 */ fflush(stdout); /* 現在就強迫送往核心,讓它顯示出來 */ long_running_work(); /* 在此期間訊息早已可見 */
沒有那個 fflush,訊息可能直到下一個換行、fclose 或正常結束前都看不見。
fflush 只把資料從 stdio 緩衝區搬到核心——它跟資料落到磁碟上不是同一回事。要真正持久,你還需要對描述符做 fsync()。在標準 C 中對輸入串流做 fflush 是未定義行為;它只對輸出有意義。