#C 语言标准库函数 setvbuf
/*********************************************
* @brief 设置缓冲区
* @param fp 文件流
* @param buffer 缓冲区
* @param mode 缓冲模式
* @param size 缓冲区大小
* @return 是(0)否(非 0)成功
********************************************/
int setvbuf(FILE* restrict fp, char* restrict buffer, int mode, size_t size);
说明
设置文件流的缓冲区和缓冲模式。
参数
fp- 要操作的文件流buffer- 指向缓冲区的指针;如果仅更改大小或模式,可以传NULLmode- 缓冲模式size- 缓冲区大小
返回值
- 成功时返回 0
- 失败时返回非 0
#缓冲模式
| 宏 | 名称 | 说明 |
|---|---|---|
_IOFBF | 全缓冲 | 缓冲区满时写入目标设备 |
_IOLBF | 行缓冲 | 缓冲区满或遇到换行符(\n)时写入目标设备 |
_IONBF | 无缓冲 | 数据直接写入目标设备 |
- 通过 fopen 打开的文件流默认使用全缓冲
- 标准输入
stdint与交互式设备(命令行终端)关联时可视作使用行缓冲,否则默认使用全缓冲 - 标准输出
stdout与交互式设备(命令行终端)关联时默认使用行缓冲,否则默认使用全缓冲 - 标准错误
stderr默认无缓冲
对于输入而言,使用缓冲意味着让 C 运行时库一次性从内核读取一块数据到用户空间内存(缓冲),程序调用 getchar 等函数时从缓冲中读取。
输入实际上不存在行缓冲,因为一次读取一块数据不可能恰好以换行符结尾;除非一个字符一个字符读取直到换行符,而这实际上是无缓冲。
与交互式设备关联时,实际上是终端处理了输入行为,在输入换行符时才将输入发送到内核,然后用户程序将整块输入读取到内存。
因此本质上用户程序的输入缓冲策略是全缓冲,但行为上可视作行缓冲。
#注意事项
必须保证缓冲区 buffer 在文件流关闭前始终有效。错误示范:
#include <stdio.h>
int main(void)
{
char buf[1024];
setvbuf(stdout, buf, _IOLBF, 1024); // 将 buf 设为 stdout 的缓冲区
return 0;
} // buf 的生命周期结束被释放
示例中 main 函数返回时局部变量 buf 立即释放,然后程序进行退出前的清理操作(包括关闭 stdout),因此 buf 在 stdout 关闭之前释放了。
#推荐阅读
#参考标准
- C17 standard (ISO/IEC 9899:2018):
- 7.21.5.6 The setvbuf function (p: 225)
- C11 standard (ISO/IEC 9899:2011):
- 7.21.5.6 The setvbuf function (p: 308)
- C99 standard (ISO/IEC 9899:1999):
- 7.19.5.6 The setvbuf function (p: 273-274)
- C89/C90 standard (ISO/IEC 9899:1990):
- 4.9.5.6 The setvbuf function