1

I would like to convert malloc() to calloc(). I am confused about using calloc() in this example because it takes 2 arguments while malloc() only one. So it's correct with mine:

(byteBuffer)calloc(sizeof(byteBufferStruct), len + 1));

The example:

typedef struct byte_buf {
    size_t  len;
    uint8_t  *bytes;
} byteBufferStruct, *byteBuffer;


byteBuffer mallocByteBuffer(size_t len)
{
    byteBuffer retval;
    if((retval = (byteBuffer) malloc(sizeof(byteBufferStruct) + len + 1)) == NULL) return NULL;
    retval->len = len;
    retval->bytes = (uint8_t *) (retval + 1) ; /* just past the byteBuffer in malloc'ed space */
    return retval;
}
  • What is confusing? The first parameter to `calloc` is `num` and the second one is `size`. – ta.speot.is Dec 18 '13 at 07:55
  • `malloc(n)` is identical to `calloc(n,1)` – mvp Dec 18 '13 at 07:56
  • i am confused about the – user3106115 Dec 18 '13 at 07:59
  • Well you want to allocate one of them so... – ta.speot.is Dec 18 '13 at 08:02
  • 1
    @mvp: no, the other way around: `malloc(n)` ~=> `calloc(1, n)` eg: `malloc(100*sizeof(char));` ~=> `calloc(100, sizeof(char));`. I know: `sizeof(char)` is 1, but I like to _see_ what I'm allocating memory for – Elias Van Ootegem Dec 18 '13 at 08:18
  • @EliasVanOotegem: you are wrong. From `man malloc`: The `calloc(size_t nmemb, size_t size)` function allocates memory for an array of `nmemb` elements of `size` bytes each. For our case, it is `n` elements of `1` byte each. – mvp Dec 18 '13 at 08:26
  • @mvp: saying `malloc(n)` is the same as `calloc(n,1)` would imply that _the first_ argument of `calloc` is the _size_ argument, whereas it clearly is the `nmemb` argument (as the man tells you). That's what I pointed out. `malloc(sizeof(struct foo));`, followed by a `memset` is ***not*** the same as `calloc(sizeof(struct foo), 1);`, the closest `calloc` gets would be `calloc(1, sizeof(struct foo));`. Your initial comment had the arguments in the wrong order: your `calloc` call would allocate an array of chars, an array of pointers would be impossible, for example – Elias Van Ootegem Dec 18 '13 at 08:32
  • @EliasVanOotegem: `calloc(n,1)` would allocate linear array of `n` bytes. So, for all intents and purposes, it is identical to `malloc(n)`. And, of course, it is the same as `calloc(1,n)`, because internally `calloc(m,n)` would simply call `malloc(m*n)` (followed by `bzero()`). – mvp Dec 18 '13 at 08:44

2 Answers2

3

First: Both malloc() and calloc() return void *, which in C means you should not cast the return value.

Comparing the signatures of the functions, we have:

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

Basically, the argument to malloc() is the product of the arguments to calloc().

You can convert by just setting one of them to 1:

void * malloc_to_calloc(size_t size)
{
   return calloc(1, size);
}

Since the nmemb (number of members) to calloc() doesn't affect the actual structure of the memory in any way, this is safe.

Now we can use this to implement your allocation function (for clarity):

byteBuffer mallocByteBuffer(size_t len)
{
  byteBuffer b = malloc_to_calloc(len + 1 + sizeof *b);
  if(b != NULL)
  {
    b->len = len;
    b->bytes = (uint8_t *) (b + 1);
  }
  return b;
}

Note that sizeof is not a function. Also note the glaring asymmetry of asterisks that you get when you typedef away the asterisk. I don't recommend ever doing that.

Community
  • 1
  • 1
unwind
  • 391,730
  • 64
  • 469
  • 606
  • it's clear now, thank you very much! (need to wait 6 min to mark it as answered) – user3106115 Dec 18 '13 at 08:00
  • I have read a long answer of you 2 months ago about not casting void (still remember your name^^). I will follow your suggestion. The code above is taken from Apple. They cast them, so newbee like me will make the same mistake. – user3106115 Dec 18 '13 at 08:18
  • @user3106115 Great! That answer is very likely the one I linked in my answer above, of course. – unwind Dec 18 '13 at 08:23
0

Instead of doing

if((retval = (byteBuffer) malloc(sizeof(byteBufferStruct) + len + 1)) == NULL) return NULL;

do

if (NULL == (retval = calloc(1, sizeof(byteBufferStruct) + len + 1))) 
  return NULL;
alk
  • 69,737
  • 10
  • 105
  • 255