I have came across this problem when using pointer to pointer to a char:
void setmemory(char** p, int num)
{
*p=(char*)malloc(num);
}
void test(void)
You are only setting the local variable *p here. Remember you are getting a pointer to data, not a pointer-to-pointer-to-data.
Think of it like this:
First case:
int a;
foo(a); // Passes a
void foo(int b)
{
b = 4; // This only changes local variable, has no effect really
}
Second case:
int a;
foo(&a); // Passes *a
void foo(int *b)
{
*b = 4; // This changes the contents of a. As you can see we have not changed the original pointer!
b = 4; // This changes our local copy of the pointer, not the pointer itself, like in the first case!
}
Third case
int *ptr;
foo(&ptr); // Passes **ptr
void foo(int **b)
{
**b = 4; // This changes the data of the passed pointer
*b = 4; // This changes the passed pointer itself, i.e. it changes ptr. This is what test() is doing, the behavior you are looking for!
b = 4; // This changes our local copy of a variable, just like the first case!
}
The orignal code is passing in the location of where the caller wants the string pointer put. If you pass in only a 'char*', the caller will pass by value the contents of the callers location - probably some uninitialized value.
If the callee has to return a string, or other indirected struct, you need both asterisks so that the callee can return a pointer into the callers pointer variable.
Does that make sense? It did to me, but then again, I wrote it.
One thing to note here is - When we say pointers, we generally tend to think in terms of pass by reference
but not necessarily. Even pointers can be passed by value
char* str
is local to test
and char* p
is local to setmemory
. So the changes you do in setmemory
will not be visible in test
if you dont send a pointer to a pointer.
You can make it work with a single pointer like this
char * setmemory(char* p, int num) // p is a new pointer but points at the same
// location as str
{
p=(char*)malloc(num); // Now, 'p' starts pointing at a different location than 'str'
strcpy(p ,"hello"); // Copy some data to the locn 'p' is pointing to
return p; // Oops. The poor `str` is still pointing at NULL :(
// Send him the address of the newly allocated area
}
void test(void)
{
char* str=NULL;
str=setmemory(str,100); // We are passing a pointer which is pointing to NULL
printf(str); //Now str points to the alloced memory and is happy :)
}
int main()
{
test();
return 0;
}
Note that in setmemory
we are returning a local pointer, but it is not a problem ( no dangling pointer problems ) as this pointer points to a location on heap and not on stack
You want to change the pointer, i.e., the function need a reference, not a value. In C, this is done by giving the address (pointer) to the variable that is by change a pointer itsself. Thus, one pointer is for referencing, the other for you porgram logic.