当fwrite写入全部元素时,是否仍可能出现写入错误?
fwrite返回值与写入错误的疑问 标准原文引用
返回值
fwrite函数返回成功写入的元素数,仅当遇到写入错误时返回值才会小于nmemb。若size或nmemb为0,fwrite返回0且流状态不变。
核心疑问
- 当返回的写入元素数小于
nmemb时,可确定发生了写入错误; - 当返回值等于
nmemb时,是否仍可能存在写入错误?
标准措辞暗示或许存在成功写入全部元素但仍遭遇写入错误的情况,想明确:当fwrite返回值等于nmemb时,写入错误是否可能存在?若存在,这意味着什么?
示例代码
#include <stdio.h> #include <stdlib.h> int main(void){ char msg[] = "hello"; size_t nmemb = sizeof msg - 1; size_t num_written = fwrite(msg, sizeof *msg, nmemb, stdout); if (num_written < nmemb) // 发生写入错误 return EXIT_FAILURE; // 是否仍可能存在写入错误? return ferror(stdout); // 这里会不会返回true?如果会意味着什么? }
具体问题
上述代码中,写入全部元素后调用ferror(stdout)是否可能返回true?若可能,这意味着什么?
结论:不可能出现这种情况
根据C23标准的描述,fwrite返回值等于nmemb时,不会存在写入错误,调用ferror也不会返回非零值。
原因分析
标准明确说明“仅当遇到写入错误时返回值才会小于nmemb”,这句话的逻辑等价于:如果返回值等于nmemb,则整个写入过程未触发任何写入错误。
这里的“写入错误”指的是fwrite在尝试写入元素时,出现无法完成写入的异常情况(比如磁盘空间耗尽、IO设备故障、管道被意外关闭等)。一旦发生这类错误,fwrite会立即终止写入操作,返回已成功写入的元素数(必然小于nmemb),同时设置流的错误标志。
如果fwrite返回了nmemb,说明所有元素都已成功写入到流的缓冲区(或直接写入底层设备),全程未触发写入错误,因此流的错误标志不会被设置,ferror会返回0。
补充说明
需要注意的是,fwrite属于带缓冲的IO函数,返回成功不代表数据已经持久化到磁盘——但这属于缓冲刷新的问题,不属于fwrite本身的写入错误。如果后续调用fflush或fclose时出现错误,那是后续操作的问题,和本次fwrite的返回值无关。
内容的提问来源于stack exchange,提问作者timmy george

