fread() 中的 "size" 参数指的是什么?

What does the "size" argument in fread() refer to?

我正在尝试制作一个复制 .wav 文件的 header 的基本程序,这是我的尝试:

#include <stdio.h>
#include <stdint.h>

int main (void)
{
    FILE* input = fopen("input.wav", "r");
    FILE* output = fopen("output.wav", "w");
    
    uint8_t header [44];
    
    fread(header, sizeof(uint8_t), 44, input);
    fwrite(header, sizeof(uint8_t), 44, output);
    
    fclose(input);
    fclose(output);
}

然而,在无法使其工作之后,我查找了如何做,显然

fread(header, sizeof(uint8_t), 44, input);
fwrite(header, sizeof(uint8_t), 44, output);

应该是

fread(header, 44, 1, input);
fwrite(header, 44, 1, output);

这让我很困惑,因为我认为第二个参数应该是您想要 fread 的数据单元类型的大小。谁能帮助我了解我所缺少的?非常感谢。

sizeof(uint8_t) 保证为 1 。有些人认为使用 sizeof 表达式而不是数字是一种很好的风格。

您可以写入 44 个大小为 1 的“块”,也可以写入 1 个大小为 44 的块。在任何一种情况下,您都尝试写入 44 个字节——两种方式的写入部分都是相同的。

不同之处在于 return 值,它报告了成功写入的块数。因此,如果您使用 1, 44 命令,那么它会准确告诉您写入了多少字节。如果您使用 44, 1 命令,那么您将获得 01 作为 return 值(并且无法知道它是否部分成功)。

同样的考虑也适用于 fread


FILE* input = fopen("input.wav", "r");部分不正确:这指定以文本模式打开文件,这可能会对输入进行翻译,例如更改行尾。

相反,使用 "rb" 模式字符串以二进制模式打开。

第一个大小参数指定单个记录的大小。第二个大小参数定义要加载的记录数。 fread returns 它加载的记录数。

因此,如果您有一个 20 字节的结构,并且您有一个文件,其中存储了 5 条记录,那么您可以像这样传递它。

if(fread(ptr, 20, 5, strm) != 5)
    printf("Unable to load 5 records\n");

或者您可以像这样加载相同的文件:

if(fread(ptr, 1, 5*20, strm) != 5*20)
    printf("Unable to load 5 records\n");

效果是一样的,但是第一个版本的可读性更好,因为通常你可能读取的记录不仅仅是“字节”。在应用程序逻辑的上下文中更容易理解。当然,您不必自己计算字节数,从而减少出错的机会。

同样适用于fwrite

所以在你上面的例子中我宁愿这样写:

  // Your header is 44 bytes long (which is sizeof) but you want to read ONE header
  if(fread(header, sizeof(header), 1, input) != 1)
     ... error reading 1 header ....