Pointers to Pointers
A pointer holds the address of a variable. Since a pointer is itself a variable stored somewhere in memory, it has its own address — and nothing stops you from storing that address in yet another pointer. That is a pointer to a pointer, declared with two asterisks: int **pp;. It looks intimidating the first time you see it, but the idea is simple: pp points to something that itself points to an int.
#include <stdio.h>
int main(void) {
int value = 42;
int *p = &value; // p points to value
int **pp = &p; // pp points to p
printf("value = %d\n", value);
printf("*p = %d\n", *p);
printf("**pp = %d\n", **pp);
return 0;
}value = 42 *p = 42 **pp = 42
Why would you need this?
The most common reason to reach for a pointer-to-pointer is that a function needs to hand back a pointer value to its caller, and C functions only return one value directly. If a function needs to both report success/failure AND produce a freshly allocated pointer, the pointer has to travel out through an output parameter — and to modify the caller's pointer variable, the function needs the address of that pointer, i.e. a pointer to a pointer.
This is exactly the same reason you pass &x to a function that needs to modify an int x — except here the "thing being modified" is itself a pointer.
Worked example: an allocate() helper
Consider a function that allocates memory for an integer, fills it with a value, and reports back the new pointer through an output parameter:
#include <stdio.h>
#include <stdlib.h>
// out is a pointer to the caller's pointer variable.
// Writing *out = ... changes what the caller's pointer points to.
int allocate(int **out, int initial_value) {
int *p = malloc(sizeof(int));
if (p == NULL) {
return 0; // failure
}
*p = initial_value;
*out = p; // hand the new address back to the caller
return 1; // success
}
int main(void) {
int *result = NULL;
if (allocate(&result, 100)) {
printf("allocated value = %d\n", *result);
free(result);
result = NULL;
} else {
printf("allocation failed\n");
}
return 0;
}allocated value = 100
Arrays of pointers: `char **`
char ** shows up constantly in real C code because it is how an array of strings is represented: each char * in the array points to one string, and a char ** points to the first char * in that array. This is precisely the type of argv in int main(int argc, char *argv[]) — argv is really a char **. We cover this in detail in the command-line arguments and array of strings pages.
int **ppis a pointer to a pointer to anint;*ppgives you theint *,**ppgives you theint.The classic use case is an output parameter: a function receives the address of the caller's pointer so it can set that pointer for them.
char **is how C represents an array of strings, includingargvinmain.Check every level of a multi-level pointer before dereferencing it — a NULL at any level crashes the same way.