This is more of a note than a reason, but the values of size
and nmemb
do make a difference as far as the return value of fread(3)
and fwrite(3)
is concerned. They return the number of elements read or written, where the size of each element is determined by the size
parameter.
POSIX also says the following re. fread()
,
If a partial element is read, its value is unspecified.
, so in theory the value of size
could make a difference for the data you get back too when the amount of data read isn't a multiple of size
(due to end-of-file or errors).
For calloc()
, the GNU C library (glibc) simply multiplies size
and nmemb
together, also checking for overflow (using a trick to quickly detect most size
and nmemb
pairs that won't overflow). Here's the relevant code from glibc 2.20 (from __libc_calloc()
in malloc/malloc.c. nmemb
and size
are called n
and elem_size
, respectively.):
/* size_t is unsigned so the behavior on overflow is defined. */
bytes = n * elem_size;
#define HALF_INTERNAL_SIZE_T \
(((INTERNAL_SIZE_T) 1) << (8 * sizeof (INTERNAL_SIZE_T) / 2))
if (__builtin_expect ((n | elem_size) >= HALF_INTERNAL_SIZE_T, 0))
{
if (elem_size != 0 && bytes / elem_size != n)
{
__set_errno (ENOMEM);
return 0;
}
}
n
and elem_size
are never referenced after that. bytes
is used instead.
The fread()
implementation (_IO_fread()
in libio/iofread.c) similarly multiplies nmemb
and size
together and only uses them to calculate the return value after that. (Unlike calloc()
, it does not check for overflow.)
I'm guessing the reasons for having two parameters might be historical. I would be interested in the answer too. Perhaps the size
parameter specified the block size of each I/O operation (or served as a hint) at some point for fread()
and fwrite()
.
Update: This answer and the comments has some interesting discussion re. calloc()
.