Hakim
Hakim

Reputation: 3437

C - modify the address of a pointer passed to a function

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

Answers (6)

arnobpl
arnobpl

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

legends2k
legends2k

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

Fekete Ferenc
Fekete Ferenc

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 (&param), 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

n0p
n0p

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

Binarian
Binarian

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

David Heffernan
David Heffernan

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

Related Questions