Search code examples
cfunctionfwrite

Confusion regarding fwrite() and fread() parameters in C


I am new to C and recently i have been working on a program whereby i am reading a stream of 512 bytes from a file using fread into a array and then after checking for certain conditions in that stream of bytes i am writing the stream of bytes into a new file using fwrite.
The code snippet for the same is

    unsigned char buffer[512];
    FILE *fp = fopen("file.name","r");

    if(fp == NULL)
    {
        perror("Error opening the file\n ");
        fclose(fp);
        return -1;
    }

    while(fread(&buffer, sizeof(buffer), 1 , fp) == 1) //my program works fine for both &buffer and only buffer
    {
          //Do something
    }

The definition of fread is:

    size_t fread(void *ptr, size_t size, size_t nmemb, FILE *stream)

Here ptr is the pointer to a block of memory where the read bytes will be stored.

I have defined buffer to be a character array and hence only passing buffer as the first parameter should have been enough as it is a pointer but the program works fine even when &buffer is being provided. The same is happening with fwrite as well. Now if buffer is the pointer then &buffer is the address of the pointer and should not have the same result as that of a pointer but it actually does, so why does the function work properly with both the different parameters?


Solution

  • In C, any data-pointer type is implicitly convertible to void*:

    • buffer designates the array. It is not a pointer. Arrays are in nearly all contexts converted to a pointer to their first elements though.
    • &buffer this is one of the exceptions, so here we have a pointer to said array instead.

    Anyway, you probably want to do this instead:

    size_t count;
    while((count = fread(buffer, 1, sizeof(buffer), fp)) > 0)
    

    Why?

    • Because you want to read all the data, and not miss the final partial block.
    • On an interactive device you want to act on the data as early as possible, not waiting until a full sizeof(buffer) block is done.