3

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?

speller
  • 1,641
  • 2
  • 20
  • 27
  • It's because of the way they are intended to work, `malloc()` doesn't care about how many elements because it's not doing anything with them, `calloc()` requires this because it initializes every element with `0` so it needs the size of each element, and I think it's pretty obvious why `fread()` wants to know that. – Iharob Al Asimi Mar 12 '15 at 22:14
  • Post the meaningful parts of your post here, – chux - Reinstate Monica Mar 13 '15 at 02:39
  • 1
    @iharob: filling 16 bytes with `0` is the same whether it's four four-byte elements or 16 one-byte elements. –  Mar 13 '15 at 10:38
  • 2
    possible duplicate of [Why calloc takes two arguments while malloc only one?](http://stackoverflow.com/questions/7536413/why-calloc-takes-two-arguments-while-malloc-only-one) – nwellnhof Mar 13 '15 at 10:44
  • Also see http://stackoverflow.com/questions/12555911/why-does-calloc-require-two-parameters-and-malloc-just-one – nos Mar 13 '15 at 11:23

2 Answers2

2

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().

Community
  • 1
  • 1
Ulfalizer
  • 4,664
  • 1
  • 21
  • 30
0

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.

Parham Alvani
  • 2,305
  • 2
  • 14
  • 25
  • Setting the bits in 16 consecutive bytes to all `0s is the same thing whether it's four four-byte elements or 16 one-byte elements. If there is a subtle difference, it requires explanation. –  Mar 13 '15 at 10:40
  • I add an example into my answer, I think it's better now. thank you. – Parham Alvani Mar 13 '15 at 12:59
  • That example would be fine for something that let you fill with an arbitrary element value, but `calloc` is fill with bit pattern all 0's. –  Mar 13 '15 at 13:06
  • I get it now, sorry I was confused it with `memset`. Thank you for pointing that. – Parham Alvani Mar 13 '15 at 13:27