Multi-Level Pointers
Double pointers, dereference chains, writing through **pp, when ** is actually needed, triple pointers.
Five pieces on int ** — a pointer to a pointer — which sounds abstract right up until it's the only way to let a function hand back a freshly allocated pointer to its caller.
int x = 10;
int *p = &x;
int **pp = &p;
printf("%d\n", **pp); /* 10 — dereference twice to get back to x */
*pp = NULL; /* this changes p itself, not x — p now points at nothing */When ** is actually needed
void allocate(int **out) {
*out = malloc(sizeof(int));
**out = 42;
}
int main(void) {
int *p;
allocate(&p); /* p itself gets set inside allocate — needs int **, not int * */
printf("%d\n", *p);
free(p);
return 0;
}A plain int *out parameter would only let allocate change what the pointer points to, not the pointer variable itself back in main. To modify the caller's pointer — make it point somewhere new — the function needs a pointer to that pointer. This exact shape shows up constantly in kernel code that allocates a resource and hands it back through an out-parameter.
Triple pointers (int ***) exist, but the only place I've actually seen them is arrays of pointers-to-pointers — genuinely rare outside of specific data structures.
Notes from readers
Comments — via GitHub