Others have answered how malloc(0)
works. I will answer one of the questions that you asked that hasn’t been answered yet (I think). The question is about realloc(malloc(0), 0)
:
What does
malloc(0)
return? Would the answer be same forrealloc(malloc(0),0)
?
The standard says this about realloc(ptr, size)
:
- if
ptr
isNULL
, it behaves likemalloc(size)
, - otherwise (
ptr
is notNULL
), it deallocates the old object pointer to byptr
and returns a pointer to a new allocated buffer. But ifsize
is 0, C89 says that the effect is equivalent tofree(ptr)
. Interestingly, I can’t find that statement in C99 draft (n1256 or n1336). In C89, the only sensible value to return in that case would beNULL
.
So, there are two cases:
malloc(0)
returnsNULL
on an implementation. Then yourrealloc()
call is equivalent torealloc(NULL, 0)
. That is equivalent tomalloc(0)
from above (and that isNULL
in this case).malloc(0)
returns non-NULL
. Then, the call is equivalent tofree(malloc(0))
. In this case,malloc(0)
andrealloc(malloc(0), 0)
are not equivalent.
Note that there is an interesting case here: in the second case, when malloc(0)
returns non-NULL
on success, it may still return NULL
to indicate failure. This will result in a call like: realloc(NULL, 0)
, which would be equivalent to malloc(0)
, which may or may not return NULL
.
I am not sure if the omission in C99 is an oversight or if it means that in C99, realloc(ptr, 0)
for non-NULL
ptr
is not equivalent to free(ptr)
. I just tried this with gcc -std=c99
, and the above is equivalent to free(ptr)
.
Edit: I think I understand what your confusion is:
Let’s look at a snippet from your example code:
ptr = malloc(0);
if (ptr == realloc(ptr, 1024))
The above is not the same as malloc(0) == realloc(malloc(0), 1024)
. In the second, the malloc()
call is made twice, whereas in the first, you’re passing a previously allocated pointer to realloc()
.
Let’s analyze the first code first. Assuming malloc(0)
doesn’t return NULL
on success, ptr
has a valid value. When you do realloc(ptr, 1024)
, realloc()
basically gives you a new buffer that has the size 1024, and the ptr
becomes invalid. A conforming implementation may return the same address as the one already in ptr
. So, your if
condition may return true. (Note, however, looking at the value of ptr
after realloc(ptr, 1024)
may be undefined behavior.)
Now the question you ask: malloc(0) == realloc(malloc(0), 1024)
. In this case, let’s assume that both the malloc(0)
on the LHS and RHS returns non-NULL
. Then, they are guaranteed to be different. Also, the return value from malloc()
on the LHS hasn’t been free()
d yet, so any other malloc()
, calloc()
, or realloc()
may not return that value. This means that if you wrote your condition as:
if (malloc(0) == realloc(malloc(0), 1024)
puts("possible");
you won’t see possible
on the output (unless both malloc()
and realloc()
fail and return NULL
).
#include <stdio.h>
#include <stdlib.h>
int main(void)
{
void *p1;
void *p2;
p1 = malloc(0);
p2 = realloc(p1, 1024);
if (p1 == p2)
puts("possible, OK");
/* Ignore the memory leaks */
if (malloc(0) == realloc(malloc(0), 1024))
puts("shouldn't happen, something is wrong");
return 0;
}
On OS X, my code didn’t output anything when I ran it. On Linux, it prints possible, OK
.