****** /---\
* 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.