5.1.12C Programming

Pointer to pointer

1,818 words8 min readdifficulty · medium

WHAT is it?

Why does the type need **? A type in C tells the compiler how to interpret the bytes at the target address. When you write *pp, the compiler must know "the thing at pp is itself a pointer," so it needs int **. One * would mean "dereferencing gives an int" — wrong, here dereferencing gives a pointer.


HOW dereferencing peels layers

Each * removes one level of indirection.

Expression Meaning Value (using addresses below)
pp address of p &p = 0x300
*pp the value stored in p &x = 0x100
**pp the value stored in x 42
Figure — Pointer to pointer

WHY do we need it? (the 80/20 core)

The 20% of use-cases that cover 80% of real code:

  1. Modifying a pointer inside a function. C passes by value. To change the caller's pointer, you must pass its address → an int **.
  2. Arrays of strings / 2-D dynamic arrays. char **argv, char **lines.
  3. Linked-list/tree edits where you must update the node-pointer itself.

Common mistakes (Steel-manned)


Flashcards

What does int **pp store?
The address of a pointer variable (a pointer to a pointer).
If pp = &p and p = &x, what is *pp?
The value of p, which is &x (the address of x).
If pp = &p and p = &x, what is **pp?
The value of x — full dereference to the int.
Why pass int ** to a function?
So the function can modify the caller's pointer, since C passes arguments by value.
How many * to modify an int vs an int* inside a function?
One * (pass int*) for an int; two * (pass int**) for a pointer.
What is the type of *pp when pp is int**?
int* — a pointer to int.
In char **argv, what is *argv?
A char* — pointer to the first command-line string.
Why does each * "peel a layer"?
Because dereference means "follow the address one step to the thing it points to."
What happens to **pp if *pp (i.e. p) is NULL?
Undefined behaviour / crash — you dereference a NULL pointer.
Does *pp = NULL change the final value x?
No — it overwrites the pointer p; x is untouched.

Recall Feynman: explain to a 12-year-old

Imagine a treasure. You have a note that says "the treasure is in box A." That note is a pointer. Now you have another note that says "the first note is on the kitchen table." That second note is a pointer to a pointer — it doesn't point to the treasure directly, it points to the note that points to the treasure. To get the treasure you read note 2 → walk to the table → read note 1 → walk to box A → open it. Each * in C is one "walk to where the note says." Two * means two walks, so you reach the treasure (42). One * only gets you to note 1.


Connections

  • Pointers basics — the single-level foundation this builds on.
  • Pass by value vs pass by referencewhy ** is needed for functions.
  • Dynamic memory allocation (malloc)int ** to return allocated memory.
  • Command line arguments (argv)char **argv in practice.
  • Pointer arithmetic — how pp+1 steps by sizeof(pointer).
  • 2-D arrays vs pointer to pointer — subtle differences in memory layout.

Concept Map

holds &x

holds &p

declared with two asterisks

equals p, yields &x

equals x, yields 42

peels via star of star_pp

enables

enables

enables

pass &q to change caller pointer

int x = 42

pointer p

pointer to pointer pp

*pp

**pp

Two levels of indirection

Modify pointer in function

Array of strings char argv

Linked-list node edits

Hinglish (regional understanding)

Intuition Hinglish mein samjho

Dekho, pointer ek aisa variable hai jo kisi doosre variable ka address store karta hai. Ab "pointer to pointer" ka matlab simple hai — ek aisa box jo kisi aur pointer ka address rakhta hai. Jaise int x = 42; phir int *p = &x; (p ke andar x ka address), aur int **pp = &p; (pp ke andar p ka address). Bas ek extra level of indirection add ho gaya, kuch magic nahi.

Yaad rakhne ka rule: har * ek arrow ko follow karta hai, ek layer chheelta hai. *pp aapko p deta hai (yaani &x), aur **pp aapko x ki value 42 deta hai. & upar le jaata hai (layer wrap karta hai), * neeche le jaata hai (layer peel karta hai). Isko mantra ki tarah yaad rakho: "Star peels, ampersand wraps."

Yeh kyun zaroori hai? Sabse bada reason — C mein function ko sab kuch by value milta hai. Agar aap function ke andar caller ka pointer hi change karna chahte ho (jaise malloc se memory de kar), toh aapko us pointer ka address bhejna padega, yaani int **. Agar aap sirf int* bhejoge, function apni local copy change karega, original waisa ka waisa reh jaayega. Isiliye void f(int **p) pattern bohot common hai.

Galti se bachna: *pp ek pointer hai (int*), aur **pp ek value hai (int) — dono interchangeable nahi hain. Arrows ginna seekh lo. Aur agar beech ka link NULL ya garbage hai, toh **pp crash kar dega. Real life examples: char **argv (command line strings), 2-D dynamic arrays, aur linked list ke node edits — sab mein yahi concept kaam aata hai.

Go deeper — visual, from zero

Test yourself — C Programming

Connections