Pointers & Memory · beginner · ~12 min

Pointer basics

Understand &address-of, *dereference, and pointer types.

Overview

A pointer is a variable whose value is a memory address. Given int x = 7;, &x produces the address of x, and int *p = &x; stores it in p. Dereferencing — *p — reads or writes the value at that address. Pointers let you share, mutate, and traverse data without copying.

Why it matters

Pointers are how C programs cooperate. You pass a pointer to a function so it can modify your data without returning a giant struct. You traverse linked lists, trees, and graphs by following pointers from node to node. You implement abstract data types by handing out opaque pointers to caller code. Almost every non-trivial C function takes or returns one.

Core concepts

Address-of (&). &x yields the address of x. Dereference (*). *p reads or writes the value at the address p points to. Pointer types. int * and char * are different types — the compiler refuses to mix them. The type determines how *p is interpreted and how pointer arithmetic advances. NULL. A pointer that doesn't point to anything has the special value NULL (often 0). Always check for NULL before dereferencing.

Syntax notes

int x = 7;
int *p = &x;        // p holds the address of x
printf("%d\n", *p); // 7  — read the int at that address
*p = 42;             // write through the pointer
printf("%d\n", x);  // 42 — x changed because we wrote via its address

Lesson

A pointer holds the address of another value. Declare it with type *name;. The & operator yields a pointer to its operand. The * operator (when used on a value, not in a declaration) yields the value at the address — "dereference".

The pointer's type matters: int *p knows its target is an int, which controls how *p reads/writes memory.

Code examples

int x = 7;
int *p = &x;     // p points to x
printf("%d\n", *p);   // 7
*p = 12;
printf("%d\n", x);   // 12

Common mistakes

  • Confusing int *p; (declaration) with *p = 12; (assignment via pointer).
  • Dereferencing an uninitialized or NULL pointer — crash.

Debugging tips

Print pointer values with %p to confirm two pointers are aliasing. In gdb, print p shows the address; print *p shows the data; info locals lists every variable in scope. NULL dereferences produce 'Segmentation fault' on Linux/macOS — that's your sign to add a null-check just before the bad read.

Memory safety

The three deadly pointer bugs: (1) NULL dereference — always check if (p) before *p. (2) Use-after-free — once you free(p), treat p as garbage and set it to NULL. (3) Wild pointer — uninitialised pointer variables hold random bytes; reading them is undefined. Initialise every pointer to NULL or a valid address.

Real-world uses

Every linked data structure, every out-parameter, every API that returns multiple values, every iterator, every callback. The Linux kernel passes pointers between subsystems thousands of times per syscall.

Practice tasks

  1. Declare an int, a pointer to it, and print both x and *p. 2. Write a void swap(int *a, int *b) function and use it. 3. Make a function that mutates a caller's int via a pointer. 4. Trigger a NULL dereference deliberately under gdb to see what it looks like.

Summary

Pointers are addresses with a type. & to take an address, * to follow one. They are the language's mechanism for sharing data — and they are also the language's biggest source of bugs. Master the patterns: initialise to NULL, null-check before deref, set to NULL after free.

Practice with these exercises