9

IMO one is enough, why does calloc require to split it into two arguments?

Jens
  • 69,818
  • 15
  • 125
  • 179
x86
  • 113
  • 1
  • 3
  • 12
    Because some programmer created it that way and thus it forever stayed... –  Sep 24 '11 at 01:45
  • 1
    If you don't like it, `#define calloc(x) (calloc)(x, 1)` ought to work. – Chris Lutz Sep 24 '11 at 01:48
  • 5
    @Chris using the preprocessor to redefine malloc or family seems like a Very Bad Idea (except maybe for debugging memory allocation). – ssube Sep 24 '11 at 01:50
  • Because calloc() requires two args; one to define the number of elements, one to define the size of the elements. BTW, calloc() clears all the allocated memory to zero. Why is this a problem? – user732933 Sep 24 '11 at 03:32
  • @peachykeen - It is. It's technically UB in the standard, though in practice it'd be insane not to work. That said, my comment wasn't really meant to be _good_ advice. – Chris Lutz Sep 24 '11 at 07:38
  • Theoretically `calloc` has an advantage in that it can allocate more than `SIZE_MAX` bytes; although some common implementations mung this up and multiply the arguments in `size_t` precision – M.M Mar 13 '15 at 10:52

2 Answers2

8

I'd guess that this is probably history and predates the times where C had prototypes for functions. At these times without a prototype the arguments basically had to be int, the typedef size_t probably wasn't even yet invented. But then INTMAX is the largest chunk you could allocate with malloc and splitting it up in two just gives you more flexibility and allows you to allocate really large arrays. Even at that times there were methods to obtain large pages from the system that where zeroed out by default, so efficiency was not so much a problem with calloc than for malloc.

Nowadays, with size_t and the function prototype at hand, this is just a daily reminder of the rich history of C.

Jens Gustedt
  • 76,821
  • 6
  • 102
  • 177
  • This doesn't answer the question at all. The width of the integer type used is completely irrelevant to this question. – Jeff Hammond Apr 20 '15 at 04:23
  • @Jeff, can you please explain? I am not saying that the width of the integer type used today has anything to do with it. I am saying that at the time the interface was created it might have been an issue. – Jens Gustedt Apr 20 '15 at 07:35
  • I object to the suggestion that it is for "really large arrays". It's bad API design to use two arguments in place of one. And why would someone want to `calloc` a pointer they could not subsequently `realloc` arbitrarily or, on which they could not use e.g. `memset` or `memcpy`? Feel free to be annoyed at my pedantry, but it would be reasonable to say something about sizeof() returning unsigned and allocating arrays _ever so slightly_ larger than `INT_MAX`. – Jeff Hammond Apr 20 '15 at 13:32
  • Furthermore, early C (K&R) had prototypes - they just weren't required for non-`int` arguments. And `long int` existed, so there was a solution to the "larger than `int`" problem even if `size_t` was not around yet. – Jeff Hammond Apr 20 '15 at 13:33
  • @Jeff, AFAIR the old style K&R parameter specification for different type than `int` doesn't provide a prototypes. Those were introduced in C89. For the inconsistency with `malloc` and `realloc` you are probably right and this is a weird choice of an interface. But unfortunately it is one of the few things that remained and that we are now stuck with. – Jens Gustedt Apr 20 '15 at 14:18
  • @Jeff, AFAIR the old style K&R parameter specification for different type than `int` doesn't provide a prototypes. Those were introduced in C89. For the inconsistency with `malloc` and `realloc` you are probably right and this is a weird choice of an interface. But unfortunately it is one of the few things that remained and that we are now stuck with. – Jens Gustedt Apr 20 '15 at 14:18
2

The parameter names document it reasonably well:

void *malloc(size_t size);
void *calloc(size_t nelem, size_t elsize);

The latter form allows for neat allocating of arrays, by providing the number of elements and element size. The same behavior can be achieved with malloc, by multiplying.

However, calloc also initializes the allocated memory to 0. malloc does no init, so the value is undefined. malloc can be faster, in theory, due to not setting all the memory; this is only likely to be noted with large amounts.

In this question, it is suggested that calloc is clear-alloc and malloc is mem-alloc.

Community
  • 1
  • 1
ssube
  • 47,010
  • 7
  • 103
  • 140
  • 4
    Another benefit of two arguments is the potential for overflow checking, normally difficult (and rarely done) with `malloc` (though if you're allocating objects of the size that might overflow you might be doing it wrong). – Chris Lutz Sep 24 '11 at 01:47
  • 2
    @Chris: Maybe we need a `cccalloc` that takes 6 arguments and allocates `a*b + c*d + e*f` bytes with overflow checking on all subexpressions... ;-) – R.. GitHub STOP HELPING ICE Sep 24 '11 at 02:02
  • 7
    I don't think that this is an answer to the question. This doesn't ask how these work (then it would just be a duplicated and should be closed). It ask for the reasoning of splitting the argument in two, instead of having just one total size as for `malloc`. – Jens Gustedt Sep 24 '11 at 07:19
  • @Jens: They do different things, particularly `calloc` clearing the memory. That's at least a good chunk of the answer. – ssube Sep 24 '11 at 08:41
  • 1
    @peachykeen, no, the fact that they do different things has nothing to do with the fact that one requires one argument and the other requires two. Both use their arguments to determine a total size of memory that is to be allocated. – Jens Gustedt Sep 24 '11 at 08:56
  • @R.. - It's obvious from the name and those parameters that it should be allocating `a * b + (c + d) * e + f` space. ;) – Chris Lutz Sep 24 '11 at 23:56
  • @Chris: As you can perhaps tell I'm a mathematician. We don't like verbose variable names. :-) – R.. GitHub STOP HELPING ICE Sep 25 '11 at 01:07
  • @R.. - I have a habit of using names like that too. `char *s, size_t l` is about as clear as I make things sometimes. – Chris Lutz Sep 25 '11 at 02:21
  • Yes those are my favorites, but some people will kill you for using `l` **ever** just because their fonts suck. ;-) My feeling is that once your function gets so large that one-letter variable names are confusing, it's probably time to re-factor... – R.. GitHub STOP HELPING ICE Sep 25 '11 at 02:31
  • calloc can be faster than malloc+memset http://stackoverflow.com/questions/2688466/why-mallocmemset-is-slower-than-calloc – phuclv Apr 18 '14 at 10:02