My very personal opinion is that pictures with arrows pointing this way or that make pointers harder to understand. It does make them seem like some abstract, mysterious entities. They are not.
Like everything else in your computer, pointers are numbers. The name "pointer" is just a fancy way of saying "a variable containing an address".
Therefore, let me stir things around by explaining how a computer actually works.
We have an int
, it has the name i
and the value 5. This is stored in memory. Like everything stored in memory, it needs an address, or we wouldn't be able to find it. Lets say i
ends up at address 0x12345678 and its buddy j
with value 6 ends up just after it. Assuming a 32-bit CPU where int is 4 bytes and pointers are 4 bytes, then the variables are stored in physical memory like this:
Address Data Meaning
0x12345678 00 00 00 05 // The variable i
0x1234567C 00 00 00 06 // The variable j
Now we want to point at these variables. We create one pointer to int, int* ip1
, and one int* ip2
. Like everything in the computer, these pointer variables get allocated somewhere in memory too. Lets assume they end up at the next adjacent addresses in memory, immediately after j
. We set the pointers to contain the addresses of the variables previously allocated: ip1=&i;
("copy the address of i into ip1") and ip2=&j
. What happens between the lines is:
Address Data Meaning
0x12345680 12 34 56 78 // The variable ip1(equal to address of i)
0x12345684 12 34 56 7C // The variable ip2(equal to address of j)
So what we got were just yet some 4 byte chunks of memory containing numbers. There's no mystical or magical arrows anywhere in sight.
In fact, just by looking at a memory dump, we can't tell whether the address 0x12345680 contains an int
or int*
. The difference is how our program chooses to use the contents stored at this address. (The task of our program is actually just to tell the CPU what to do with these numbers.)
Then we add yet another level of indirection with int** ipp = &ip1;
. Again, we just get a chunk of memory:
Address Data Meaning
0x12345688 12 34 56 80 // The variable ipp
The pattern does seem familiar. Yet another chunk of 4 bytes containing a number.
Now, if we had a memory dump of the above fictional little RAM, we could manually check where these pointers point. We peek at what's stored at the address of the ipp
variable and find the contents 0x12345680. Which is of course the address where ip1
is stored. We can go to that address, check the contents there, and find the address of i
, and then finally we can go to that address and find the number 5.
So if we take the contents of ipp, *ipp
, we will get the address of the pointer variable ip1
. By writing *ipp=ip2
we copy ip2 into ip1, it is equivalent to ip1=ip2
. In either case we would get
Address Data Meaning
0x12345680 12 34 56 7C // The variable ip1
0x12345684 12 34 56 7C // The variable ip2
(These examples were given for a big endian CPU)