You're absolutely right. Your c array in the second example is being allocated on the stack, and thus the memory will get reused immediately following. In particular, if you had code like
printf("%s\n",greet());
you'd get weird results, because the call to printf would have reused some of the space of your array.
The solution is to allocate the memory somewhere else. For expample:
char c[] = "Hello";
char * greet() {
return c;
}
Would work. Another choice would be to allocate it statically in scope:
char * greet() {
static char c[] = "Hello";
return c;
}
because static memory is allocated separately from the stack in data space.
Your third choice is to allocate it on the heap via malloc:
char * greet() {
char * c = (char *) malloc(strlen("Hello")+1); /* +1 for the null */
strcpy(c, "Hello");
return c;
}
but now you have to make sure that memory is freed somehow, or else you have a memory leak.
Update
One of those things that seems more confusing than I expect is what exactly a "memory leak" is. A leak is hen you allocate memory dynamically, but lose the address so it can't be freed. None of these examples necessarily has a leak, but only the third one even potentially has a leak, because it's the only one that allocates memory dynamically. So, assuming the third implementation, you could write this code:
{
/* stuff happens */
printf("%s\n", greet());
}
This has a leak; the pointer to the malloc'ed memory is returned, the printf
uses it, and then it's lost; you can't free it any longer. On the other hand,
{
char * cp ;
/* stuff happens */
cp = greet();
printf("%s\n", cp);
free(cp);
}
doesn't leak, because the pointer is saved in an auto variable cp
long enough to call free()
on it. Now, even though cp disappears as soon as execution passes he end brace, since free has been called, the memory is reclaimed and didn't leak.