student@ubuntu:~$
Topic Week 5 3 min overview

Pointers

The address-of operator you have been using with scanf, generalized into the feature that makes C usable

In a nutshell

A pointer is a variable that holds a memory address instead of a value. You have already used pointers, briefly, every time you wrote scanf("%d", &age). This topic generalizes that mechanic: any variable has an address (get it with &x), any address can be dereferenced (read or write the value with *p), and functions that take pointer parameters can modify a caller’s variables — the thing pass-by-value made impossible last week. Arrays decay to pointers in most expressions, which is why scanf("%s", name) works without &. Pointer arithmetic (p + n advances by n elements, not n bytes) is how you walk arrays without array subscripts.

Why it matters

You cannot write idiomatic C without pointers. Every non-trivial C function either takes or returns a pointer. Strings are pointers. File handles are pointers. Dynamically allocated memory is accessed through pointers. Linked lists, trees, and every data structure beyond a fixed-size array use pointers. And every exploitable memory bug in the history of C (use-after-free, double-free, buffer overflow, format string) is ultimately a pointer bug.

Key takeaways

  • &x gives the address of x; *p dereferences (reads or writes the value at p). int *p = &x; *p = 42; sets x to 42.
  • NULL is a pointer to no object. Check if (p == NULL) before dereferencing anything that could be NULL.
  • A pointer has a type. int * points to an int; char * points to a char. The type tells the compiler the size of the target and how arithmetic scales.
  • Pass-by-pointer lets a function modify the caller. void swap(int *a, int *b) works; void swap(int a, int b) does not.
  • Array-to-pointer decay. In most expressions, an array name becomes a pointer to its first element. arr[i] is exactly *(arr + i).
  • Pointer arithmetic scales by type size. int *p; p + 3 advances by 3 * sizeof(int) bytes, not 3 bytes.
  • A pointer is always 8 bytes on a 64-bit machine, regardless of what it points to. sizeof(int *) is 8 even though sizeof(int) is 4.
  • Double pointers (int **) appear whenever a function needs to modify a pointer the caller owns (think argv, realloc-style resizing).

Lessons in this topic

Lesson What it covers
Pointer Basics &, *, NULL, declaring a pointer, reading and writing through one
Pass-by-Pointer Functions that modify the caller’s variables, including the mental model for scanf
Pointer Arithmetic & Array Duality p + n, p - q, arr[i] as *(arr + i), walking an array without subscripts
Double Pointers int **, when you need one, the argv pattern, modifying a caller’s pointer

Practice and deep dives

Practice this topic: Pointers or Double Pointers drills, or browse the practice gallery.

For the machine-level picture (what &x resolves to on the stack, array-to-pointer decay explained, variadic promotions for printf), see the machine model deep dive.

What comes next

Dynamic Memory — pointers that come from the heap. malloc returns a pointer to memory you asked for. free returns it. Every pointer bug pattern you have read about (double-free, use-after-free, memory leak) lives here.