fread读取WAV文件头到uint8_t数组的参数逻辑疑问
fread两种传参方式的区别解答 先给结论:你提到的两种写法都能正确把44字节文件头读入数组,不会引发内存错误,编译器完全可以正常处理,二者的核心差异不在内存读写逻辑,而在返回值语义和代码表意的清晰度上。
首先先明确fread的函数定义:
size_t fread(void *ptr, size_t size_per_element, size_t element_num, FILE *stream);
它从文件中读取的总字节数永远是 size_per_element * element_num,按这个公式计算:
- 写法1:
fread(header, HEADER_SIZE, 1, input)总读取字节数是HEADER_SIZE * 1 = 44 - 写法2:
fread(header, sizeof(uint8_t), HEADER_SIZE, input)总读取字节数是1 * HEADER_SIZE = 44
二者要读的总字节数完全一致,且header数组本身已经开辟了连续的44字节内存空间,fread本身对目标指针的类型没有要求(第一个参数是void*,只会按字节顺序把二进制数据拷贝到对应内存位置),根本不会管你数组的元素是1字节还是多字节,所以不存在“单字节数组不能一次性读多字节”的问题。
两种写法的实际区别只有两点:
- 返回值含义不同:
fread的返回值是成功读取的完整元素个数,不是总字节数。第一种写法把整个WAV头当做1个不可拆分的逻辑元素,读成功就返回1,读失败(比如文件长度不足44字节、IO错误)就返回0,你只需要判断返回值是否等于1,就能直接确认整个文件头是不是完整读入,判断逻辑非常直接。第二种写法把每个字节当做一个独立元素,返回值范围是0到44之间的任意整数,哪怕文件损坏只读到20字节的残缺头,也会返回20,你必须额外判断返回值是否等于HEADER_SIZE才能确认头是完整的,步骤更繁琐。 - 代码表意不同:第一种写法直接告诉读代码的人,你当前要读的是一个长度为HEADER_SIZE的完整整体(也就是WAV文件头),和你的业务逻辑完全匹配;第二种写法则表意是要读HEADER_SIZE个单字节数据,看不出你读的是一个完整的文件头结构,可读性更差。
实际写代码时选哪种传参逻辑,只需要看你读取的内容是不是逻辑上的整体:读固定长度的文件头、结构体这类不能拆分的内容,就把整体长度作为单元素大小,元素数传1;读同类型数据组成的长数组(比如WAV文件里后续的音频采样数据),就把单个采样的大小作为单元素大小,元素数传要读的采样总数,更方便统计有效读取的元素个数。
内容的提问来源于stack exchange,提问作者Maria
相关产品推荐
相关产品推荐

