为何调用fgetc()后需额外添加fseek()才能使fputc()生效?
为什么在fgetc()后直接调用fputc()无效,添加fseek(fp,0,SEEK_CUR)却能正常工作?
在使用r+模式打开文件后,执行以下操作时遇到异常:
- 用
fseek(fp, 4, SEEK_SET)将文件指针定位到第4位 - 调用
fgetc()读取字符,此时指针移动到第5位 - 直接调用
fputc()写入新字符,文件无任何变化
但在fputc()前添加fseek(fp, 0, SEEK_CUR)(无实际位移)后,写入操作正常生效。
原代码如下:
#include <stdio.h> #include <stdlib.h> int main() { FILE *fp; char ch; char c[100]; fp = fopen("file12.txt", "r+"); if (fp == NULL) { printf("ERROR"); exit(1); } fseek(fp, 4, SEEK_SET); printf("%c", fgetc(fp)); // fseek(fp, 0, SEEK_CUR); fputc('M', fp); fclose(fp); return 0; }
原因分析
这是C标准库文件流操作的读写切换规则导致的:
- 当文件以更新模式(
r+)打开时,标准明确规定:在没有先执行定位函数(fseek/fsetpos/rewind)或刷新函数(fflush)的情况下,不能直接从读操作切换到写操作,反之亦然。 - 你先执行了
fgetc()读操作,此时流处于读状态,直接调用fputc()属于违规切换,行为是未定义的(可能被忽略、覆盖错误位置或导致其他异常)。 fseek(fp, 0, SEEK_CUR)虽然没有改变指针的实际位置,但它属于标准认可的定位操作,会触发流状态的切换,让库正确处理后续的写操作,因此fputc()能正常写入到目标位置。
补充说明:C17标准§7.21.5.3章节明确了这一规则——更新流上的读操作和写操作之间必须有一个定位或刷新操作,否则行为未定义。
内容的提问来源于stack exchange,提问作者muntasir mk
相关产品推荐
相关产品推荐

