C Notes
Master double pointers (pointer to pointer) in C including declaration, usage with functions, dynamic 2D arrays, and practical applications with memory diagrams.
A double pointer (or pointer to pointer) is a variable that stores the address of another pointer. Just as a regular pointer stores the address of a variable, a double pointer stores the address of a pointer variable. This concept extends naturally — you can have triple pointers, quadruple pointers, and so on — though in practice, you rarely need more than two levels of indirection.
What is a Double Pointer?
int x = 42;
int *p = &x; // p stores address of x
int **pp = &p; // pp stores address of pDeclaration and Usage
#include <stdio.h>
int main() {
int x = 100;
int *p = &x;
int **pp = &p;
printf("x = %d\n", x);
printf("*p = %d\n", *p);
printf("**pp = %d\n", **pp);
printf("\n&x = %p\n", (void*)&x);
printf("p = %p\n", (void*)p);
printf("*pp = %p\n", (void*)*pp);
printf("\n&p = %p\n", (void*)&p);
printf("pp = %p\n", (void*)pp);
// Modify x through double pointer
**pp = 200;
printf("\nAfter **pp = 200: x = %d\n", x);
return 0;
}x = 100 *p = 100 **pp = 100 &x = 0x7ffd1000 p = 0x7ffd1000 *pp = 0x7ffd1000 &p = 0x7ffd1008 pp = 0x7ffd1008 After **pp = 200: x = 200
Why Do We Need Double Pointers?
Use Case 1: Modifying a Pointer Inside a Function
Just as you need a pointer to modify an int inside a function, you need a pointer-to-pointer to modify a pointer inside a function:
After allocateWrong: arr1 = (nil) (still NULL!) After allocateRight: arr2 = 0x55a4e0001260 (allocated!) arr2[0] = 42
Use Case 2: Dynamic 2D Arrays
Double pointers are the standard way to create dynamically sized 2D arrays:
Dynamic 2D Array (3x4): 1 2 3 4 5 6 7 8 9 10 11 12
Memory Layout of Dynamic 2D Array
| matrix | ┌─────────┐ |
| │ row0_ptr─┼── | [1][2][3][4] |
| │ row1_ptr─┼── | [5][6][7][8] |
| │ row2_ptr─┼── | [9][10][11][12] |
| Note | Each row can be at a DIFFERENT location in heap memory. |
Use Case 3: Array of Strings (Command-Line Arguments)
The main function's argv parameter is a classic double pointer:
Program: ./myprogram Arguments (3 total): argv[1] = "hello" argv[2] = "world"
Use Case 4: Linked List Operations
Double pointers simplify linked list insertion/deletion by avoiding special cases for the head pointer:
#include <stdio.h>
#include <stdlib.h>
typedef struct Node {
int data;
struct Node *next;
} Node;
// Without double pointer: need to return new head
Node* insertFront(Node *head, int value) {
Node *newNode = (Node *)malloc(sizeof(Node));
newNode->data = value;
newNode->next = head;
return newNode; // Caller must update head
}
// With double pointer: modifies head directly
void insertFrontDP(Node **head, int value) {
Node *newNode = (Node *)malloc(sizeof(Node));
newNode->data = value;
newNode->next = *head;
*head = newNode; // Directly modifies the caller's head pointer
}
void printList(Node *head) {
while (head) {
printf("%d → ", head->data);
head = head->next;
}
printf("NULL\n");
}
int main() {
Node *list = NULL;
insertFrontDP(&list, 30);
insertFrontDP(&list, 20);
insertFrontDP(&list, 10);
printList(list);
// Cleanup (simplified)
while (list) {
Node *temp = list;
list = list->next;
free(temp);
}
return 0;
}10 → 20 → 30 → NULL
Triple Pointers (Rare but Valid)
#include <stdio.h>
int main() {
int x = 5;
int *p = &x;
int **pp = &p;
int ***ppp = &pp;
printf("x = %d\n", x);
printf("*p = %d\n", *p);
printf("**pp = %d\n", **pp);
printf("***ppp = %d\n", ***ppp);
***ppp = 99;
printf("\nAfter ***ppp = 99: x = %d\n", x);
return 0;
}x = 5 *p = 5 **pp = 5 ***ppp = 5 After ***ppp = 99: x = 99
Common Mistakes with Double Pointers
Interview Questions
Q1: When would you use a double pointer instead of a single pointer?
When you need to modify a pointer itself inside a function (not just the value it points to). Common cases: dynamic memory allocation functions, linked list operations that change the head pointer, and creating dynamic 2D arrays.
Q2: What's the difference between a 2D array and a double pointer in terms of memory layout?
A static 2D array (int arr[3][4]) stores all elements contiguously in a single block. A double pointer (int **arr) stores row pointers contiguously, but each row's data can be scattered across the heap. This means static 2D arrays have better cache performance.
Q3: How does char argv work in main?**
argv is a pointer to an array of char* strings. argv[0] is the program name, argv[1] through argv[argc-1] are the command-line arguments. Each argv[i] is itself a char* pointing to a null-terminated string.
Q4: Can you have a pointer to a pointer to a pointer? When is it useful?
Yes (int ***ppp). It's occasionally useful for dynamic 3D arrays or when a function needs to modify a double pointer. However, beyond two levels of indirection, code becomes hard to read, and alternative designs (like structs) are usually preferred.
Summary
- A double pointer (
int **pp) stores the address of a pointer variable - Use double pointers when a function needs to modify a pointer (not just the pointed-to value)
- Dynamic 2D arrays use
int **with separatemallocfor each row main'sargvparameter is a classic double pointer (char **argv)- Always free inner allocations before outer ones to prevent memory leaks
- Double pointers simplify linked list operations by avoiding head-pointer special cases
Exam Focus
Revise definitions, diagrams, examples, and short-answer points for Double Pointers in C - Pointer to Pointer.
Interview Use
Prepare one clear explanation, one practical example, and one common mistake for this C Programming topic.
Search Terms
c-programming, c programming, programming, pointers, double, double pointers in c - pointer to pointer
Related C Programming Topics