The unary *
operator is used both to declare a pointer and access the value at that pointer’s location. When the value is the address of another pointer, two *
unary operators are used. When the value is the address of an address of an address of an address, then four *
unary operators are used. I kid you not.
Here is code that will either tickle your fancy or fill you with icy cold fear:
#include <:stdio.h> int main() { int i; int *a,**b,***c,****d; i = 4; a = &i; b = &a; c = &b; d = &c; printf("Variable i = %d\n",i); printf("Variable *a = %d\n",*a); printf("Variable **b = %d\n",**b); printf("Variable ***c = %d\n",***c); printf("Variable ****d = %d\n",****d); return(0); }
The code compiles. It runs. Here’s the output:
Variable i = 4
Variable *a = 4
Variable **b = 4
Variable ***c = 4
Variable ****d = 4
That’s actually very predictable. And it all makes sense, if you take it one step at a time.
Start with variable i
. It’s an int variable. The value is set to 4 at Line 8. The value is displayed at Line 14. It’s a simple, basic procedure, something you’d find in some early Chapter in any C programming book.
Next, consider variable a
. It’s an int pointer, declared by using *a
at Line 6. It’s assigned to the address of int variable i
at Line 9; the unary &
operator makes the address (memory location) assignment. At Line 15, the value stored at a
‘s address is displayed. That value is 4.
Remember, a
is the address, and *a
is the value at the address.
In Line 10, variable b
is assigned the address of pointer variable a
. The **
declaration (at Line 6) means variable b
is designed to hold the address of another pointer variable — pointer a
— which holds the address of another variable — int variable i
. It’s a pointer to a pointer.
A pointer to a pointer is how you say **b
. “Pointer-pointer variable b
.” Although sometimes I call it a double-dingbat.
Line 11 initializes pointer-to-a-pointer-to-a-pointer variable c
to hold the address of pointer-to-a-pointer variable b
. That works. It’s completely unnecessary, lacking any realistic purpose in any code, but it works.
Finally, Line 12 assigns the address of variable c
to variable d
. Just say “pointer” several dozen times in your head and you’ll get the terms correct but still probably not understand what’s going on. That’s okay.
The printf() statements running from Lines 14 through 18 display values, which are all the same.
The C language allows you to create pointer-to-pointer (etc.) types of variables, providing you properly initialize them. After all, a ***
type of variable can only hold the address of a **
type of variable. It’s really nuts. You could even have a variable declared like this:
int ******************q;
That works, and you could use the variable, but it could reference only another pointer variable, declared with one fewer asterisk and initialized to another pointer variable declared with two fewer asterisks. That’s just silly.
No, the deepest you go in the C language with pointers is the **
pointer, a pointer-to-a-pointer. Most often, if not all the time, such a construction is used to reference and manipulate an array of pointers, typically an array of strings.