What is a double pointer (pointer to pointer) and when do you use it?
A double pointer (pointer to pointer) is a variable that stores the address of another pointer. Declared with two asterisks **, it adds a second level of indirection.
Common use cases:
- Modifying a pointer inside a function -- if you want a function to change where a pointer points (not just the value it points to), you pass a pointer to that pointer.
- Dynamic 2D arrays -- an array of pointers, where each pointer points to a row.
- Pointer arrays --
char **argvinmain()is a pointer to an array ofchar *.
How dereferencing works:
ppis the address of the pointer*ppis the pointer itself (the address of the final value)**ppis the actual value
The classic interview pattern is a function that allocates memory and returns it through a parameter rather than a return value.
1. Declare pointer: int *p = &value
2. Declare double pointer: int **pp = &p
3. *pp gives you p (the pointer)
4. **pp gives you value (the pointed-to data)
5. To modify a pointer in a function, pass &p to a function accepting int **
#include <stdio.h>
#include <stdlib.h>
/* Function that allocates memory and returns it via double pointer */
void allocate(int **pp, int value) {
*pp = (int *)malloc(sizeof(int));
if (*pp != NULL) {
**pp = value;
}
}
int main(void) {
int x = 10;
int *p = &x;
int **pp = &p;
printf("x = %d\n", x); /* 10 */
printf("*p = %d\n", *p); /* 10 */
printf("**pp = %d\n", **pp); /* 10 */
/* Modify x through double pointer */
**pp = 42;
printf("x after **pp = 42: %d\n", x); /* 42 */
/* Allocate memory through a function */
int *dynamic = NULL;
allocate(&dynamic, 99);
printf("dynamic value: %d\n", *dynamic); /* 99 */
free(dynamic);
return 0;
}
- •A double pointer stores the address of a pointer variable
- •Dereferencing once (*pp) gives the pointer, twice (**pp) gives the value
- •Essential for functions that need to modify the caller's pointer (e.g., allocate memory)
- •char **argv is the most common real-world double pointer
- •Each level of indirection adds one * to the declaration
- •Forgetting to pass the address of the pointer (&p) instead of the pointer itself (p) when calling a function that expects int **
- •Dereferencing a double pointer that points to a NULL pointer causes a segfault
- •Memory allocated inside a function via double pointer must still be freed by the caller
- •Triple pointers (int ***) are almost always a design smell -- refactor with structs instead