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

CS50x Volume实验:文件读入内存再写入与直接读写的差异

哈佛CS50x Volume实验文件读写问题解析

在CS50x的Volume实验中,你遇到了两种文件读写方式的差异:先将WAV文件内容读入内存数组再写入输出文件的代码能正常调整音量,但直接调用fread把输入内容读取到输出文件指针的方式会生成无效输出文件,核心原因是对fread参数的理解错误,以下是两种方式的详细差异:

一、正确的读写方式(内存缓冲区中转)

这种方式通过内存数组作为中间载体,完成输入到输出的数据传递,代码逻辑如下:

// 正确:用内存数组作为缓冲区复制文件头
uint8_t arr[HEADER_SIZE];
fread(arr, sizeof(uint8_t), HEADER_SIZE, input);
fwrite(arr, sizeof(uint8_t), HEADER_SIZE, output);

// 处理音频采样
int16_t buffer;
while (fread(&buffer, sizeof(int16_t), 1, input))
{
    buffer = buffer * factor;
    fwrite(&buffer, sizeof(int16_t), 1, output);
}

逻辑说明:

  • fread的第一个参数是内存缓冲区的起始地址(这里是arr数组的地址),它会把输入文件的内容读取到这块内存区域
  • 之后调用fwrite,把内存缓冲区里的内容写入到输出文件中
  • 整个流程是:输入文件 → 内存缓冲区 → 输出文件,完全符合C标准库文件IO的设计逻辑,数据传递路径清晰且安全

二、错误的读写方式(误用FILE指针作为缓冲区)

你尝试的错误代码中,核心问题是对fread参数的误用:

// 错误:直接将FILE指针传给fread的第一个参数
fread(output, sizeof(uint8_t), HEADER_SIZE, input);

错误原因:

  • output是FILE*类型的指针,它指向的是C标准库内部维护的文件控制结构体,这个结构体里存储的是文件描述符、IO缓冲区位置、文件状态等管理信息,根本不是用来存储文件内容的缓冲区
  • 调用fread(output, ...)相当于把输入文件的头数据直接写入到这个文件控制结构体的内存空间中,直接破坏了标准库对输出文件的管理状态,导致后续的fwrite操作无法正常和输出文件交互,最终生成的输出文件因为头数据错误或文件结构损坏而无效

总结

C标准库的文件IO函数中,fread/fwrite的第一个参数必须是用于存储数据的内存缓冲区地址,而不是FILE*指针。前者是数据的临时存储区域,后者是文件的管理句柄,二者完全不是同一个概念,混用会直接破坏文件IO的底层逻辑,导致程序生成无效文件。

内容的提问来源于stack exchange,提问作者Sahil Gautam

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.05 19:25:50