You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

C语言中在putw操作后调用fread为什么会导致文件体积变大?

问题现象

我尝试使用fread()从文件读取数据时,发现文件体积一直在持续增长,该行为不符合读取场景的预期。我编写了如下测试代码复现问题:使用putw()向文件写入数据后,不关闭重新打开的文件就直接读取时,fread会为了完成读取操作扩大文件体积。

测试环境

  • 操作系统:Windows 8.1
  • 编译器:MinGW gcc

测试代码

typedef struct {
    int a;
    int b;
} A;
int main() {
    FILE* f = fopen("file", "wb");
    A a;
    a.a = 2;
    a.b = 3;
    putw(1, f);
    fwrite(&a, sizeof(A), 1, f);
    fclose(f); // 排除wb模式和fwrite导致该问题的可能性
    f = fopen("file", "rb+");
    printf("initial position: %ld\n", ftell(f));
    putw(1, f);
    printf("position after putw: %ld\n", ftell(f));
    printf("fread result: %d\n", fread(&a, sizeof(A), 1, f));
    printf("position after 1st fread: %ld\n", ftell(f));
    printf("fread result: %d\n", fread(&a, sizeof(A), 1, f));
    printf("position after 2nd fread: %ld\n", ftell(f));
    fclose(f);
    remove("file");
    return 0;
}

运行结果

initial position: 0
position after putw: 4
fread result: 1
position after 1st fread: 12
fread result: 1
position after 2nd fread: 20
问题原因

这是因为你违反了C标准中对带+的更新模式文件流的操作规则:

C11标准7.21.5.3第7段明确规定:当以更新模式打开文件时,流上可以同时执行输入和输出操作。但输出操作后不能直接跟随输入操作,输入操作后也不能直接跟随输出操作,除非满足以下两个条件之一:

  1. 中间执行了fflush刷新输出缓冲区,或执行了fseek/fsetpos/rewind等文件定位操作
  2. 输入操作遇到了文件结束符

你的代码在rb+模式的流上执行完putw(输出操作)后,没有进行任何刷新或定位操作就直接调用fread(输入操作),属于未定义行为。你观测到的文件自动扩大,是MinGW运行库对该未定义行为的具体实现表现。

修复方案

在putw操作完成后、第一次fread调用前,添加文件定位操作即可,比如你需要从当前指针位置(偏移量4)开始读取,可以添加:

fseek(f, ftell(f), SEEK_SET);

修复后第二次fread会返回0(表示已读到文件末尾,无更多数据),也不会出现文件体积异常扩大的问题。

内容的提问来源于stack exchange,提问作者Navid Naseri

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.01 15:24:03