Why does calloc
take two arguments instead of one like malloc
?
Specifically, since there is no difference between (or is there?) between th
calloc(x,y)
is a equivalent to malloc(x*y)
But calloc
doing additional (setting values to 0 with) memset(block, 0, x*y)
This function is only for pretty way pass the size of element and number of elements, when in malloc you must multiply this values to get needed number of bytes, this function check integer overflow too in multiplication.
For example if you want allocate memory for 12 integers and you want do something with this integers and you must have setted her values to 0, use calloc(12, sizeof(int))
But if you want allocate some memory block (256 bytes) to copy in future to it some string then memset
is a not usable for you, then better use is malloc(sizeof(char) * 256)
or for example malloc(sizeof(wchar_t) * 256)
void *
calloc (size_t nmemb, size_t lsize)
{
void *ptr;
struct __meminfo *info;
size_t size = lsize * nmemb;
/* if size overflow occurs, then set errno to ENOMEM and return NULL */
if (nmemb && lsize != (size / nmemb))
{
set_errno (ENOMEM);
return NULL;
}
/* allocate memory */
ptr = malloc (size);
/* get pointer to info part of chunk */
info = __mem2info (ptr);
/* fill memory with zeros and set __MEM_CALLOC flag */
memset (ptr, 0, info->size);
info->flags |= __MEM_CALLOC;
return ptr; /* happy end */
}
The only notable difference is that calloc
is required to initialize the allocated space to zeroes while there is no such guarantee with malloc
. Otherwise, I guess there are two different functions just for historical reasons.
Everything is just bytes is a relatively new (ie c/Unix era) invention - on a lot of other architecture things were fixed sized records.
I heard two [mutually exclusive] explanations for why it has two arguments:
calloc
takes the responsibility for checking for overflow on multiplication. If the total size of the requested block is too large (like overflows size_t
), calloc
returns null pointer to indicate failure. With malloc
you have to watch for overflow yourself, which many people simply forget to do. (Although the history of standard library knows examples of calloc
implementations that ignored overflow, and thus worked incorrectly).
calloc
actually allows one to allocate bigger blocks of memory than the range of type size_t
, i.e. calloc
might be capable of performing the proper non-overflowing large multiplication of its arguments and allocate the block of the resultant size. For this reason, since calloc
uses two arguments of type size_t
, it can allocate bigger blocks than malloc
will ever be able to (since malloc
takes only one argument of type size_t
).
I always believed that the first explanation is the right one. However, after reading some posts here on SO I have my doubts.
I believe that malloc is guaranteed to return an area of memory which is aligned according to the coarsest requirement that would be compatible with the size indicated by the second argument. For example, if the system requires alignment of 2 and 4-byte integers, and the second argument is 10, the returned pointer must be aligned on a two-byte boundary; if the second argument were 12, the pointer would be aligned on a four-byte boundary. I suspect that in practice many systems will align all returned pointers to the largest possibly-required boundary, regardless of size, but I don't think it's required except for calloc.