Pointer to pointer clarification

I was following this tutorial about how does a pointer to a pointer work.

Let me quote the relevant passage:


    int i = 5, j = 6, k = 7;
    int *ip1 = &i, *ip2 = &j;

Now we can set

    int **ipp = &ip1;

and ipp points to ip1 which points to i. *ipp is ip1, and **ipp is i, or 5. We can illustrate the situation, with our familiar box-and-arrow notation, like this:

enter image description here

If then we say

    *ipp = ip2;

we've changed the pointer pointed to by ipp (that is, ip1) to contain a copy of ip2, so that it (ip1) now points at j:

enter image description here


My question is: Why in the second picture, is ipp still pointing to ip1 but not ip2?


Forget for a second about the pointing analogy. What a pointer really contains is a memory address. The & is the "address of" operator - i.e. it returns the address in memory of an object. The * operator gives you the object a pointer refers to, i.e. given a pointer containing an address, it returns the object at that memory address. So when you do *ipp = ip2, what you are doing is *ipp get the object at the address held in ipp which is ip1 and then assign to ip1 the value stored in ip2, which is the address of j.

Simply
& --> Address of
* --> Value at


Because you changed the value pointed to by ipp not the value of ipp. So, ipp still points to ip1 (the value of ipp), ip1's value is now the same as ip2's value, so they both point to j.

This:

*ipp = ip2;

is the same as:

ip1 = ip2;

Like most beginner questions in the C tag, this question can be answered by going back to first principles:

  • A pointer is a kind of value.
  • A variable contains a value.
  • The & operator turns a variable into a pointer.
  • The * operator turns a pointer into a variable.

(Technically I should say "lvalue" instead of "variable", but I feel it is more clear to describe mutable storage locations as "variables".)

So we have variables:

int i = 5, j = 6;
int *ip1 = &i, *ip2 = &j;

Variable ip1 contains a pointer. The & operator turns i into a pointer and that pointer value is assigned to ip1. So ip1 contains a pointer to i.

Variable ip2 contains a pointer. The & operator turns j into a pointer and that pointer is assigned to ip2. So ip2 contains a pointer to j.

int **ipp = &ip1;

Variable ipp contains a pointer. The & operator turns variable ip1 into a pointer and that pointer value is assigned to ipp. So ipp contains a pointer to ip1.

Let's sum up the story so far:

  • i contains 5
  • j contains 6
  • ip1 contains "pointer to i"
  • ip2 contains "pointer to j"
  • ipp contains "pointer to ip1"

Now we say

*ipp = ip2;

The * operator turns a pointer back into a variable. We fetch the value of ipp, which is "pointer to ip1 and turn it into a variable. What variable? ip1 of course!

Therefore this is simply another way of saying

ip1 = ip2;

So we fetch the value of ip2. What is it? "pointer to j". We assign that pointer value to ip1, so ip1 is now "pointer to j"

We only changed one thing: the value of ip1:

  • i contains 5
  • j contains 6
  • ip1 contains "pointer to j"
  • ip2 contains "pointer to j"
  • ipp contains "pointer to ip1"

Why does ipp still point to ip1 and not ip2?

A variable changes when you assign to it. Count the assignments; there cannot be more changes to variables than there are assignments! You start by assigning to i, j, ip1, ip2 and ipp. You then assign to *ipp, which as we've seen means the same as "assign to ip1". Since you didn't assign to ipp a second time, it didn't change!

If you wanted to change ipp then you'll have to actually assign to ipp:

ipp = &ip2;

for instance.


hope this piece of code can help.

#include <iostream>
#include <stdio.h>
using namespace std;

int main()
{
    int i = 5, j = 6, k = 7;
    int *ip1 = &i, *ip2 = &j;
    int** ipp = &ip1;
    printf("address of value i: %p\n", &i);
    printf("address of value j: %p\n", &j);
    printf("value ip1: %p\n", ip1);
    printf("value ip2: %p\n", ip2);
    printf("value ipp: %p\n", ipp);
    printf("address value of ipp: %p\n", *ipp);
    printf("value of address value of ipp: %d\n", **ipp);
    *ipp = ip2;
    printf("value ipp: %p\n", ipp);
    printf("address value of ipp: %p\n", *ipp);
    printf("value of address value of ipp: %d\n", **ipp);
}

it outputs:

enter image description here