In Chapter 8, “Pointers,” we stated a pointer can point to any kind of variable. Since a pointer is a variable, you can make it the target of another pointer, creating a pointer to a pointer. This concept is useful in itself and is also important for understanding the equivalence of array notation and pointer notation, which is explained in the next section.
The program PTRPTR.C demonstrates a pointer to a pointer in simple terms:
/* PTRPTR.C: Demonstrate a pointer to a pointer. */
#include <stdio.h>
main()
{
int val = 501;
int *ptr = &val;
int **ptr_ptr = &ptr;
printf( "val = %d\n", **ptr_ptr );
}
Here is the output from PTRPTR.C:
val = 501
The first two statements in PTRPTR.C should look familiar by now. They create an int variable named val and an int pointer named ptr. The third line, however, requires some explanation:
int **ptr_ptr = &ptr;
This statement uses double indirection to create a variable named ptr_ptr, which is a pointer to a pointer. This pointer is assigned the address of the first pointer, ptr. The pointer ptr references val, and the pointer ptr_ptr references ptr. Figure 9.1 illustrates the relationship between ptr and ptr_ptr.
Once we have initialized both pointers, we can use ptr_ptr to access val:
**ptr_ptr
Summary: The double indirection operator ( ** ) is used with a pointer to a pointer.
The double indirection operator (**) in front of ptr_ptr tells two things about ptr_ptr: that ptr_ptr is itself a pointer and it points to a second pointer. Both asterisks are needed to access the contents of val. If you use only one, as in
*ptr_ptr
then ptr_ptr accesses the contents of ptr, which is the address of val. This statement, for instance, prints the address stored in ptr:
printf( "ptr = %u", *ptr_ptr );
Using pointers to pointers is known as “multiple indirection.” One pointer points to a second pointer, which in turn accesses a third data object. In theory, there's no limit to how far you can take multiple indirection. You can create pointers to pointers, pointers to pointers to pointers, and so on. However, there's rarely any practical reason to carry indirection beyond two levels (a pointer to a pointer).