$ overview
overview/0x09·Pointers & Memory

Pointers

Variables that hold addresses: the idea that everything else builds on.

Every variable lives at some address in memory. A pointer is a variable whose value is an address — instead of holding a number or a character, it holds the location of one. This is the idea the rest of C's more advanced features are built on.

Address-of and dereference

basics.c
1int age = 19;
2int *p = &age; // p now holds the address of age
3 
4printf("%d\n", age); // 19
5printf("%p\n", (void*)p); // some address, e.g. 0x7ffee2a1c9ac
6printf("%d\n", *p); // 19 — dereferencing p reads what it points to
  • &age — "the address of age."
  • int *p — declares p as a pointer to an int.
  • *p — "the value at the address p holds," used both to read and to write through a pointer.

Writing through a pointer

write-through.c
1int age = 19;
2int *p = &age;
3 
4*p = 20; // changes age itself, not just p
5printf("%d\n", age); // 20

This is exactly what makes scanf("%d", &age) work: scanf receives the address of age and writes through it, which is the only way a function can modify a variable that belongs to its caller.

Pointers as function parameters

Recall from 0x06 that C passes arguments by value — a function can't change the caller's variable directly. Passing a pointer works around this, since the function can dereference it to reach the original:

swap.c
1void increment(int *n) {
2 *n = *n + 1; // modifies the caller's variable
3}
4 
5int main(void) {
6 int x = 5;
7 increment(&x);
8 printf("%d\n", x); // 6
9 return 0;
10}

NULL and invalid pointers

A pointer that isn't pointing anywhere valid should be set to NULL, and checked before it's dereferenced:

null-check.c
1int *p = NULL;
2 
3if (p != NULL) {
4 printf("%d\n", *p);
5}
error: Dereferencing NULL or garbage crashes your program
Reading or writing through a pointer that's NULL, uninitialized, or already freed is undefined behavior — usually a crash, sometimes silent corruption. There's no automatic check; it's on you to know what a pointer points to before you use it.

Pointer types matter

A pointer's declared type tells the compiler how many bytes to read or write, and how far to move for arithmetic — an int * and a double * holding the same address behave very differently when dereferenced.