Reputation: 3437
I don't understand why the modification of pointer
address passed as parameter
to a function
isn't persisted outside of this function (the address of ptr
doesn't change after this function is called):
void advance(int *ptr) {
ptr = ptr + 1
}
When I can inside this same function modify the value
pointed by ptr
: *ptr = *ptr + 1
.
PS: I know that I can achieve what I want using a pointer to a pointer
: **ptr
.
Upvotes: 2
Views: 2417
Reputation: 1236
See the function:
void demonstrate(int num) {
num = num + 1; // type of num is int
} // destroys "num", because num's scope is only "demonstrate" function
In your function:
void advance(int *ptr) {
ptr = ptr + 1; // type of ptr is int* and ptr is incremented
} // destroys "ptr" for the similar reason
But you want a function that modifies an address (IN pointer). So the complete solution should be:
#include <stdio.h>
void advance(int **ptr) { //ptr is a pointer to a pointer
// so *ptr is the pointer that is pointed by ptr
*ptr = *ptr + 1; // incrementing the address IN the pointer pointed by ptr
} // destroys "ptr" for the reason above
int main() {
int x = 5;
// initially assign "ptrToChange"
int *ptrToChange = &x;
// "ptrToChange" now points to x
// passing address OF "ptrToChange" to "advance" function
advance(&ptrToChange);
// now "ptrToChange" does NOT point to x
return 0;
}
Upvotes: 0
Reputation: 32994
****** /---\ * 20 * ----> | 2 | ****** \---/ i 20-24
Here i
is a pointer pointing to the memory location 20
which has a value 2
i.e. when the binary data in 20 + sizeof(int) - 1
is interpreted as a decimal number. Now, when you pass i
to advance
, which has an argument ptr
, what really happens is
****** /---\ ****** * 20 * ----> | 2 | <---- * 20 * ****** \---/ ****** i 20-24 ptr
ptr = i;
i.e. the value of i
is set to the value of ptr
, which are really addresses here, since i
and ptr
are pointers.
When you increment ptr
it'll just make the pointer point to a different address and not change anything with respect to i
since ptr
is a copy and not i
itself. However, if you change the value at ptr
using the operator *
i.e. as *ptr = 10
; then the 2
above will change to 10
thereby change *i
as well, which is also pointing to 20. Again notice that i
's address or value is untouched, only the location to which it is pointing to underwent a change. Had there been 10 pointers pointing to the address 20
, even then none of them get changed, but all their pointed-to value gets changed.
Upvotes: 0
Reputation: 119
When you define the function void advance(int *ptr) it means that a pointer in the stack will be created, which pointer points to the same addres as the original pointer. To see the proof try printing the address of orig pointer (&orig) and the address of the parameter pointer (¶m), and the "pointed to" addresses (orig,param). The pointer addresses will differ, but the pointed to addresses will be the same.
So we have two pointers that points to the same area, if you modify the param, it will point to the new area, but the orig value will not be changed, it points to the same area as before.
That's why you need a pointer to a pointer. If you use a pointer to a pointer (int **ppointer = &orig), you will have a pointer that directly points to the area where orig stores the "pointed to" address (to where the orig points currently). By changing the value of the *ppointer, you will directly change the value of the orig as well.
Upvotes: 2
Reputation: 3496
You actually answered you own question ;)
the modification of pointer address passed as parameter to a function isnt persisted outside of this function
Inside the function you are managing a copy of your parameter. You can modify the value pointed because you are explicitly asking for change at a specific address.
Upvotes: 0
Reputation: 12446
Because C is not call by reference, it is always call-by-value, even with references/pointers as arguments.
It is not like other languages, where it can differentiate between argument types.
Upvotes: 1
Reputation: 613461
This behaviour is because parameters to functions in C are always passed by value. What you are passing by value here is an address. When you modify ptr
you are modifying a copy of the caller's value.
To modify the caller's value you need an extra level of indirection:
void advance(int **ptr) {
*ptr = *ptr + 1;
}
Upvotes: 2