C 程式設計/stdio.h/setvbuf
setvbuf 是標準 C 中的一個函式,它允許程式設計師控制檔案流的緩衝。它在 <stdio.h> 中宣告;它的函式原型是
int setvbuf(FILE *stream, char *buf, int mode, size_t size);
stream 引數是指向檔案流的指標,相關緩衝操作將在該檔案流上執行;buf 是一個長度為 size 的字元陣列,或者是一個空指標;mode 是所需的緩衝型別:_IOFBF,表示全緩衝,_IOLBF 表示行緩衝,_IONBF 表示不緩衝。這三個宏定義在 <stdio.h> 中。setvbuf 在成功時返回零,在失敗時返回非零值。
如果 buf 是空指標,系統將動態分配一個指定大小(size 個字元)的緩衝區。如果 mode 是 _IONBF,則流 I/O 將不會被緩衝,導致流上的每個後續 I/O 操作都會立即執行,並且 buf 和 size 引數會被忽略。
一個相關的函式,setbuf 也控制檔案流的緩衝。與 setvbuf 不同,setbuf 只接受兩個引數。原型是
void setbuf(FILE *stream, char *buf);
setbuf 的行為等效於
(void)setvbuf(stream, buf, buf ? _IOFBF : _IONBF, BUFSIZ);
也就是說,如果 buf 不是 NULL,則使用給定的緩衝區將流設定為全緩衝;否則,將流設定為不緩衝。如果向 setbuf 提供緩衝區,則緩衝區必須至少 BUFSIZ 位元組長。該函式總是成功。
下面的程式碼非常不穩定,可能在特定的編譯器上無法正常工作。它甚至可能導致緩衝區溢位.. C99 規定在寫入流之後不能呼叫 setvbuf,因此此程式碼呼叫了未定義的行為。C99 腳註 230(非規範性)指出,應該在 main 結束時釋放 buf 之前關閉流。
此程式的輸出應該是 Hello world 後面跟著一個換行符。請注意,此示例是錯誤的,因為它實現了 manpage 清楚標記為錯誤的內容:緩衝區需要在流關閉時仍然存在。在這裡,緩衝區在離開 main 時消失,但流僅在程式終止後關閉。
#include <stdio.h>
#include <stdlib.h>
int main(void) {
char buf[42];
if(setvbuf(stdout, buf, _IOFBF, sizeof buf)) {
perror("failed to change the buffer of stdout");
return EXIT_FAILURE;
}
printf("He");
/* The buffer contains "He"; nothing is written yet to stdout */
fflush(stdout); /* "He" is actually written to stdout */
if(setvbuf(stdout, NULL, _IONBF, 0)) {
perror("failed to change the buffer of stdout");
return EXIT_FAILURE;
}
printf("llo w"); /* "llo w" is written to stdout, there is no buffering */
if(setvbuf(stdout, buf, _IOLBF, sizeof buf)) {
perror("failed to change the buffer of stdout");
return EXIT_FAILURE;
}
printf("orld"); /* The buffer now contains "orld"; nothing is written yet to stdout */
putchar('\n'); /* stdout is line buffered; everything in the buffer is now written to stdout along with the newline */
return EXIT_SUCCESS;
}