问题
See: http://pubs.opengroup.org/onlinepubs/009695399/functions/malloc.html
The malloc function simply gets a array size to allocate.
But: http://pubs.opengroup.org/onlinepubs/009695399/functions/calloc.html
And: http://pubs.opengroup.org/onlinepubs/009695399/functions/fread.html
Are just 2 examples of functions that receive element size and number of elements.
Why's that difference? Doesn't it more simple to get a size and that's it?
回答1:
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()
.
回答2:
I think in calloc
and fread
functions want put values in array's elements so it must put them one by one if it put all of them at one time this may cause problem because your cpu may be in [little-endian] (http://en.wikipedia.org/wiki/Endianness) order.
for example if you want to set four element into 1 in little-endian machine:
element size = 2 bytes:
| 01 00 | 01 00 | 01 00 | 00 01 |
element size = 3 bytes:
| 01 00 00 | 01 00 00 | 01 00 00 | 01 00 00 |
and for fread
, It's based on how fread is implemented.
The Single UNIX Specification says
For each object, size calls shall be made to the fgetc() function and the results stored, in the order read, in an array of unsigned char exactly overlaying the object.
来源:https://stackoverflow.com/questions/29021191/why-do-some-posix-functions-get-a-element-number-and-element-size-parameters