Search code examples
cfread

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


I'm trying to make a basic program which copies the header of a .wav file, this was my attempt:

#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);
}

However, after failing to make it work, I looked up how to do it and apparently

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

should be

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

This is very confusing to me, as I thought that the second argument was supposed to be the size of the type of data unit you want to fread. Can anyone help me understand what I'm missing? Many thanks.


Solution

  • The first size parameter specifies the size of a single record. The second size parameter defines how many records you want to load. fread returns the number of records it loaded.

    So if you have a structure which is 20 bytes, and you have a file where you have stored 5 of the records then you can pass it like this.

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

    Alternativaly you could load the same file like this:

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

    The effect is the same, but the first version is more readable, because usually you may read records not just "bytes". It's easier to understand in the context of your application logic. And of course you don't have to deal with calculating the number of bytes yourself, thus reducing a chance for errors.

    The same applies to fwrite.

    So in your above example I would rather write it like this:

      // 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 ....