Home

Memory Masterclass: Pointers, Pointers-to-Pointers, and the Stack

When programming in C, understanding the layout of memory is the key to unlocking the true power of the machine. This reference guide traces how variables, pointers, and pointers-to-pointers occupy physical space in your computer’s RAM, utilizing a complete program breakdown and real-world analogies to illustrate these foundational concepts.

The Complete Code Reference

Here is the finalized program analyzing these memory relationships:

#include <stdio.h>

int main(void) {
    int var = 49;
    int *ptr = &var;
    int *null_p = NULL;
    int **p2p = &ptr;

    printf("var:  %d\n", var);
    printf("Address of var:  %p\n", (void *)&var);

    *ptr = 108;
    printf("new var value is: %d\n", var);
    printf("Address of var is still:  %p\n", (void *)&var);
    printf("Address held in pointer is:  %p\n", (void *)ptr);

    if (null_p == NULL) {
        printf("Pointer null_p initialized\n");
    }

    printf("The var value hold in p2p pointer is: %d\n", **p2p);
    printf("The address of p2p pointer is: %p\n", (void *)&p2p);
    printf("The address of ptr pointer is: %p\n", (void *)&ptr);

    **p2p = 49;
    printf("new var value modified by **p2p is: %d\n", var);

    return 0;
}

Expected Console Output

When running this code on a standard 64-bit system, you will see output similar to this.

(Note: The exact hexadecimal numbers starting with 0x will vary every time the program runs due to security features like Address Space Layout Randomization (ASLR), but the mathematical relationships between them remain constant.)

var:  49
Address of var:  0x7ffeefbff4ac
new var value is: 108
Address of var is still:  0x7ffeefbff4ac
Address held in pointer is:  0x7ffeefbff4ac
Pointer null_p initialized
The var value hold in p2p pointer is: 108
The address of p2p pointer is: 0x7ffeefbff498
The address of ptr pointer is: 0x7ffeefbff4a0
new var value modified by **p2p is: 49

The Memory Box & Locker Analogy

To understand how pointers chain together, imagine a row of school lockers. Each locker represents a memory box. Every locker has a unique locker number painted on the outside (its memory address) and contains something inside it (its value).

Based on your program’s architecture, we can map out three specific memory boxes:

Variable Data Type Physical Address (Locker #) Value Stored Inside Analogy Meaning
var int 0x7ffeefbff4ac 4910849 A box holding a regular integer value.
ptr int * 0x7ffeefbff4a0 0x7ffeefbff4ac (Address of var) A box containing a note: “Go look inside Locker 4ac.”
p2p int ** 0x7ffeefbff498 0x7ffeefbff4a0 (Address of ptr) A box containing a note: “Go look inside Locker 4a0.”

Because ptr and p2p are distinct variables, they require their own independent physical memory slots. There are exactly three unique memory addresses involved to store these three variables.

Decoding the Syntax: Values vs. Addresses

Keeping track of whether an expression evaluates to a value or a memory address depends on two critical operators:

From the program’s updated printf statements, we see how adding & shifts the focus to the tracking variables themselves:

Jumping the Chain with Double Dereference

Because p2p is a pointer-to-pointer, you can bypass the middleman (ptr) entirely by dereferencing twice (**). Writing **p2p = 49; follows p2p to ptr, follows ptr to var, and safely alters the data inside var directly from two steps away.

The Neighborhoods of Memory: The Floor Analogy

Computer memory is structurally organized into distinct regions, which you can think of as completely different floors of a building. Where a variable lives depends entirely on how it was created.

The Stack Floor

When you declare local variables inside a function (like var, ptr, and p2p inside main()), they are allocated automatically on the Stack.

The Heap Floor

If you allocate memory dynamically using malloc(), that data is placed in a completely separate region called the Heap. The Stack floor and the Heap floor live far apart and grow toward each other from opposite ends of the architecture. If you compare a Stack address to a Heap address, the numbers look completely different, reflecting this massive spatial separation.

Tags: CPointersMemoryStackProgramming