Both calloc()
, fread
and fwrite()
will attempt the same work with count and size arguments swapped. Incidentally these arguments are specified in a different order for fread
/fwrite
and calloc
:
size_t fread(void *ptr, size_t size, size_t nmemb, FILE *stream);
size_t fwrite(const void *ptr, size_t size, size_t nmemb, FILE *stream);
void *calloc(size_t nmemb, size_t size);
While it makes no difference for calloc()
, transposing the arguments in fread()
and fwrite()
has an effect on the return value, which is the number of elements successfully read or written. Make sure you use the correct values and compare the return value with the nmemb
argument (the third argument):
#include <stdio.h>
struct chunk {
int a, b, c;
};
size_t copy_chunks(FILE *from, FILE *to) {
struct chunk array[64];
size_t total = 0, nread, nwritten;
while ((nread = fread(array, sizeof(*array), 64)) != 0) {
nwritten = fread(array, sizeof(*array), nread);
total += nwritten;
if (nwritten != nread) {
fprintf(stderr, "write error: wrote %zu of %zu elements\n", nwritten, nread);
break;
}
return total;
}
Note that it is indeterminate how many bytes were actually written in case of write error above.
Here is the text from the C Standard:
7.21.8.2 The fwrite
function
Synopsis
size_t fwrite(const void * restrict ptr,
size_t size, size_t nmemb,
FILE * restrict stream);
The fwrite
function writes, from the array pointed to by ptr
, up to nmemb
elements whose size is specified by size
, to the stream pointed to by stream
. For each object, size
calls are made to the fputc
function, taking the values (in order) from an array of unsigned char
exactly overlaying the object. The file position indicator for the stream (if defined) is advanced by the number of characters successfully written. If an error occurs, the resulting value of the file position indicator for the stream is indeterminate.
Returns
The fwrite
function returns the number of elements successfully written, which will be less than nmemb
only if a write error is encountered. If size
or nmemb
is zero, fwrite
returns zero and the state of the stream remains unchanged.
If you do not care about the return value, it makes no difference indeed... but ignoring errors can make a difference depending on the consequences of unexpected circumstances. Also think about later readers of your code and make it easier for them to understand what it does by using the proper arguments.
Other library functions take a void *
pointer, a size and a count argument and the behavior is deeply affected if not undefined if you pass them in the wrong order:
void *bsearch(const void *key, const void *base,
size_t nmemb, size_t size,
int (*compar)(const void *, const void *));
void qsort(void *base, size_t nmemb, size_t size,
int (*compar)(const void *, const void *));
void *bsearch_s(const void *key, const void *base,
rsize_t nmemb, rsize_t size,
int (*compar)(const void *k, const void *y, void *context),
void *context);
errno_t qsort_s(void *base, rsize_t nmemb, rsize_t size,
int (*compar)(const void *x, const void *y, void *context),
void *context);