Multiple indirection generally occurs in the following scenarios: writing to a parameter of pointer type, and building an N-dimensional array by pieces.
Writing to a parameter of pointer type
For any function parameter of type T, if you want the function to modify the value of the parameter and have that new value reflected in the caller, you must pass a pointer:
void foo( T *ptr ) { *ptr = new_value(); // writes new value to thing pointed to by ptr } void bar( void ) { T var; foo( &var ); // writes new value to var }
The expression *ptr in foo refers to the same object in memory as var in bar, so writing to *ptr is equivalent to writing to var.
If T is a pointer type Q *, then you wind up with a pointer to a pointer:
void foo( Q **ptr ) { *ptr = new_value(); // writes new value to thing pointed to by ptr } void bar( void ) { Q *var; foo( &var ); // writes new value to var }
In this second case, you want to modify the pointer value stored in var. Again, both *ptr and var refer to the same memory location, but this time, var contains a pointer value. You could replace Q with R *, giving
void foo( R ***ptr ) { *ptr = new_value(); // writes new value to thing pointed to by ptr } void bar( void ) { R **var; foo( &var ); // writes new value to var }
The semantics are the same in all three cases; we write a new value to var through the expression *ptr; it's just the type of var is a pointer type, meaning the type of ptr must be a pointer type with one more level of indirection.
Building an N-dimensional array by pieces
Suppose you want to allocate an NxM array of T, but you don't know the values of N or M at compile time. One approach is to declare a pointer to a pointer, then allocate an array of pointers to it:
T **arr; // arr will point to an NxM array of T size_t n, m; /** * get values for n and m */ arr = malloc( sizeof *arr * n ); // allocate N objects of type T * if ( arr ) { for ( size_t i = 0; i < n; i++ ) { arr[i] = malloc( sizeof *arr[i] * m ); // allocate M objects of type T if ( arr[i] ) { for ( size_t j = 0; i < m; i++ ) { arr[i][j] = some_value(); } } } }
The same general mechanism can be applied for higher-dimensioned arrays:
T ***arr3; ... arr3 = malloc( sizeof *arr3 * n ); ... arr3[i] = malloc( sizeof *arr3[i] * m ); ... arr3[i][j] = malloc( sizeof *arr3[i][j] * k );
There are a few other scenarios where you see multiple indirection, but those are the two main ones.
It's rare in practice to see more than three levels of indirection, though.
n. You dereference it once you get the pointer it was pointing to, dereference it twice you get the object pointed to by the pointerptr_ptris pointing to.