22

Possible Duplicate:
Why calloc takes two arguments while malloc only one?

There are lots of resources describing the difference in functionality between malloc and calloc, but I can't easily find one that describes the history behind the differing function signatures:

   void *calloc(size_t nmemb, size_t size);
   void *malloc(size_t size);

Of course, the size in the former is the size for each member. Maybe the idea was that multiple-of-the-page-size member size callocs could be done lazily via the operating system?

(I can make up reasons as well as the next guy -- no accepted answers without cited sources. :-) )

user5534993
  • 518
  • 2
  • 17
cdleary
  • 69,512
  • 53
  • 163
  • 191
  • Extremely related: http://stackoverflow.com/q/7536413/142019 –  Sep 28 '11 at 09:47
  • 2
    No citations, so just a comment -- the `calloc` signature is more usable, since a proper implementation checks for overflow on multiply, relieving the caller of the responsibility. I suspect one of two explanations: (1) `malloc` came first, and it's just a compatibility thing, (2) `calloc` is expected to be slower because of the zero-ing, and someone thought that the multiply and overflow check in `malloc` should be omitted for speed. – Steve Jessop Sep 28 '11 at 09:49
  • 2
    I find it odd that a question can be closed as an exact duplicate of a less specific question with no satisfying (or accepted) answers -- I'm wondering how the two signatures arose historically. – cdleary Sep 28 '11 at 18:10

1 Answers1

1

This is somewhat open to interpretation of the language used in the C specification.

The language here seems very carefully chosen - malloc is defined in section 7.20.3.3 as:

The malloc function allocates space for an object whose size is specified by size and whose value is indeterminate.

Earlier an object was defined in section 3.14 as:

region of data storage in the execution environment, the contents of which can represent values

calloc on the other hand is defined in 7.20.3.1 as:

The calloc function allocates space for an array of nmemb objects, each of whose size is size. The space is initialized to all bits zero.

This should make it obvious. The difference between calloc and malloc is that calloc allocates memory for an array of n conceptual objects, although in practice this is no different from a call to malloc which allocates space for 1 conceptual object of size (n * size).

So the next question is... what is the need for the distinction between space for an array of objects and space for one large object?

From a programmers perspective the two function calls are just asking for different things. One is asking for a big hunk of memory to be assigned - and I'll deal with it. The other is saying - I want an array of n things which are of this size, give me some memory which I could use for this array, and zero it - because in most implementations I can make good assumptions about what zeroed memory means.

The fact that you are trying to use it as malloc + zeroing is, by my reading of the specification, a misunderstanding about the purpose of the function.

They ended up with different signatures because they do different things.


Some cute side thoughts... A trivial malloc implementation can look like:

#define malloc(x) (calloc(1, x))

It is also fun to note that if my NULL pointer representation is not zeroed, then calloc won't return me an array of NULL pointers. Better yet, if I design an integer representation in which zeroed memory is not ((int)0), calloc won't return me an array of 0s.

James Greenhalgh
  • 2,401
  • 18
  • 17
  • So you're basically saying that `calloc` returns an array of initialized objects (granted that all-bits-zero isn't guaranteed to be a valid object for all types on all implementations, it is at least a reasonable attempt at initialization), whereas `malloc` returns raw uninitialized memory for an object or an array? – Steve Jessop Sep 28 '11 at 11:55
  • 1
    Regarding your fun notes - you could in fact design an implementation in which all-bits-zero is a trap representation of every type except `char` and `signed/unsigned char`, rendering `calloc` almost useless. As a corollary, `calloc` is almost useless in strictly conforming programs, and its second parameter is entirely useless in strictly conforming programs since the only types it's useful for have size 1. – Steve Jessop Sep 28 '11 at 12:01
  • @Steve Jessop: Trap representations are not a problem as long as you don't evaluate them - you can overwrite them just fine in a strictly conforming program. – caf Sep 28 '11 at 12:29
  • @caf: agreed, so fair enough `calloc`'s two parameters are still useful in that they do the overflow check. I should have said that calloc's property of clearing the memory is almost useless in strictly etc. And if you're going to overwrite all the memory before reading it as anything other than a character type, that turns `calloc` (by comparison with `malloc`) into a potentially very expensive way of doing an overflow check. – Steve Jessop Sep 28 '11 at 12:32
  • 2
    For integer types, all-bits-zero is always a representation (perhaps not the only one) of 0. This wasn't stated in the C90 or C99 ISO standard, but it was added in one of the Technical Corrigenda (see n1256.pdf). Presumably the committee felt free to add this requirement because all existing implementations already satisfy it. There's no such guarantee for floating or pointer types. – Keith Thompson Sep 28 '11 at 15:30
  • 1
    @KeithThompson: Is `malloc(sizeof(double))` guaranteed to reutrn a validly-aligned `*double`? What about `calloc(sizeof(double),1)` [as distinct from `calloc(1,sizeof(double))`]? While I would be surprised at any system where memory allocations didn't always satisfy what was required for the longest type, I would think such a system might not necessarily be forbidden. – supercat Oct 27 '12 at 19:29
  • @supercat: Both `malloc()` and `calloc()` are guaranteed to return pointers suitably aligned for any type. See [N1570](http://www.open-std.org/jtc1/sc22/wg14/www/docs/n1570.pdf) 7.22.3 (N1570 is the latest draft of the 2011 ISO C standard). – Keith Thompson Oct 27 '12 at 19:41