Reputation: 2735
Can someone explain / give a reasoning to me on why the value of variable i in main function in below code snippet does not change via function test1 while it does change via test2? I think a single pointer should be sufficient to change the value of i. Why are we supposed to use double pointer?
#include <stdio.h>
void test1(int* pp)
{
int myVar = 9999;
pp = &myVar;
}
void test2(int** pp)
{
int myVar = 9999;
*pp = &myVar;
}
int main()
{
printf("Hej\n");
int i=1234;
int* p1;
p1 = &i;
test1(p1);
printf("does not change..., p1=%d\n",*p1);
test2(&p1);
printf("changes..., p1=%d\n",*p1);
return 0;
}
Upvotes: 5
Views: 9189
Reputation: 21351
In C parameters are passed by value. This means that in test1
when you pass pp
a copy is made of the pointer and when you change it the change is made to the copy not the pointer itself. With test2
the copy is of a double pointer but when you dereference and assign here
*pp = &myVar;
you are changing what is being pointed to, not changing pp
itself. Take note that this behaviour in test2
is undefined as is documented in some of the other answers here
Upvotes: 6
Reputation: 613572
void test1(int* pp)
{
int myVar = 9999;
pp = &myVar;
}
This function is passed a pointer pp
. The function modifies that pointer. But since parameters are passed by value, that modification is not seen by the caller.
You need to write the function like this:
void test1(int* pp)
{
*pp = 9999;
}
The caller of this function is expected to pass the address of an int
variable. The function then writes an int
value, 9999 in this case, to that address. This is the key. You are passed an address, and you then write a value to that address. Your broken version simply modified the address. You were missing the indirection.
When the function returns, the caller can observe the modification to the int
variable whose address was passed to the function. The calling code can look like this:
int i = 0;
test1(&i); // pass address of int variable
printf("%d\n", i); // prints the new value, 9999
void test2(int** pp)
{
int myVar = 9999;
*pp = &myVar;
}
Now, this is broken in a very serious way. This function does indeed return a pointer to the caller. But it returns a pointer to an object that goes out of scope as soon as the function returns. That is known as undefined behaviour. Don't do this. Never pass out of a function, a pointer to a local variable defined in that function.
Upvotes: 2
Reputation: 9234
int* p1;
p1 = &i;
test1(p1); //1st
test2(&p1); //2nd
In simple way , 1st is pass by value
and 2nd is pass by address
.
Description :
In first case it passing pointer is actually the copy of that p
inside test1
so the pp
inside test1 is the local to that function and it's created in test1
. You assigned the address and when comes out of function it's destroyed.
But in second case you are passing the address of the pointer to test2
function. So the pointer pp
in test2
will point to the pointer p
in main so assigning a new address to pp
using *pp = &myVar
will automatically set the value of p
(since you are dereferencing the pointer). Hence when test2
terminates still p
will point to modified location.
Upvotes: 0
Reputation: 2051
But you're not changing the value of i
, you're changing the address that pp
points to, if you only want to change the value of i
then it's enough to change your test to:
void test3(int* pp)
{
int myVar = 9999;
*pp = myVar;
}
Upvotes: 4
Reputation: 42215
pp = &myVar;
assigns the address of myVar
to the pointer pp
. If you want to change the value that pp
points to, use
*pp = myVar;
instead.
In answer to your second question, pass a pointer to a pointer when you want to change the object pointed to rather than changing the value of your existing object.
Upvotes: 1
Reputation: 85897
Because f(x)
can't change the value of x
, no matter whether x is an int, a float, or a pointer.
Upvotes: 2
Reputation: 105975
If you want to change the value of a variable of type T
you have to use a pointer on that type (T*
). Since you want to change a pointer (T = int*
), you have to provide a pointer to a pointer (T* = int**
), otherwise you're only going to change the copy.
Note that
int myVar = 9999;
*pp = &myVar;
will result in undefined behavior, since pp
will now contain the address of a local variable which isn't valid after you exit the function.
Upvotes: 3