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