I am just reading the C++ tutorial from this site and stumbled upon some understanding problems concerning pointers. On page 71 there is a discussion on "Pointers on Pointers". There is an example with the expression
char ** c;
It is then argued that this can have three meanings (which leads to different values):
1. c has type char **
2. c* has type char *
3. c** has type char
I am not sure if I understand the exact meaning here and therefore cannot understand the example. Could someone please explain exactly how to discern these cases?
It's not about "discerning the cases". All three are true, at all times. Read it aloud in words:
**c is a character
*c is a pointer to a character
c is a pointer to a pointer to a character
1 2 3 4 5 6 7 8 9 10
char** ppc;
char* pc;
char c;
**ppc = *pc; // Assign char to char
**pcc = c; // Idem
*ppc = pc; // Assign pointer to char to pointer to char
*ppc = &c; // Assign pointer to char an address of a char
ppc = &pc; // Assign pointer to pointer to char the address of a pointer to char
ppc = &&c; // This will throw errors because it is meaningless, but "grammatically" it is correct
char a;
char * b;
char ** c;
a = 'z';
b = &a;
c = &b;
+----+ +----+ +----+
| &B |--->| &A |--->| Z |
+----+ +----+ +----+
C B A
If you look at the value of C it has the address of where B can be found.
If you look at the value of what C is pointing to (ie *C) you go to C find the address of what it is pointing to and get the value of that, in this case it is the address of A.
If you dreference C again (ie **C), you go to c find that address, follow it to B, and follow that address to A and the value of that is the letter Z.
So,
C has the value of &B
*C has the value of &A
**C has the value of Z
Found your example. I'm not sure how you can follow the rest if you don't understand this part, but okay.
Think of it this way: a variable is actually just a value saved at a memory address. The internal workings of the system map the variable names to memory addresses (don't ask me how; it doesn't matter anyway).
In this case, there's a char variable ('z') saved at a memory slot ('7230') (the actual number is meaningless; in your debugger, you'll see a hex number that changes at every runtime). Secondly, we have a pointer to a char. It, too, is a value ('7230') saved at a memory slot ('8092'). The only change is that the value is an address rather than a char. Because it is of type *char, we know the value at the address pointed to is to be interpreted as a char. Thirdly, we have a pointer to a pointer to a char. Again, it is a value ('8092') saved at a memory slot ('10502').
Now, if I use variable c, the system knows I'm talking about the value saved at 10502 (internally). Because the compiler knows c is of type char**, it knows that *c (dereferenced once) is a char* and **c (dereferenced twice, equal to *(*c)) is a char.
Basically, pointers are just an easy way to keep track of a variable. If 'a' is ever assigned a new value, any copy we have would be invalid (and we'd have no way of knowing). However, since 'a' will still be at the same memory slot, b and c would still be correct, as they would still be keeping track of 'a', regardless of any changes that happen to it.
@Grey Wolf and Gaminic
Thanks to you both, I think I get it now. I don't know where the confusion came from. Perhaps one has to do more exercises with this stuff, as usual.