Pointer Basics
Variables that hold addressesEvery variable lives at an address in memory. A pointer is a variable that stores such an address. In the lab below you take an address with &, follow it with * to read and change a variable without using its name, see the difference between copying an address and copying a value, and meet NULL and the dangerous wild pointer.
- &xthe address of x
- int *pa variable that holds an address
- *pthe value at that address
Ready
Keyboard: ← → step · Space play / pause · R reset · Esc exit classroom mode
The ideas behind the lab
Exactly what you watched happen, in plain steps.
Address, pointer, dereference
Memory is a long row of numbered bytes; the number of a byte is its address. Every variable occupies some bytes, and &x gives the address of the first one. A pointer is a variable whose value is such an address — int *p means "p holds the address of an int". Writing *p (dereferencing) follows the address: *p is the int stored there, and you can read it or assign to it.
int x = 7;
int *p = &x; // p holds the address of x
printf("%d", *p); // 7 — read x through p
*p = 20; // x is now 20
int *q = NULL; // points nowhere (test with q != NULL)
int *w; // wild: holds garbage — never use it
| Expression | Type | Value | Meaning |
|---|---|---|---|
| x | int | 7 | The variable |
| &x | int * | 0x7ffe1000 | The address of x |
| p | int * | 0x7ffe1000 | The pointer's value: an address |
| *p | int | 7 | The int at that address (x itself) |
| &p | int ** | 0x7ffe1008 | Where the pointer itself is stored |
| sizeof p | size_t | 8 | Every pointer is 8 bytes on 64-bit systems |
The two operators
- & (address-of) gives where a variable is stored: &x.
- * (dereference) follows an address to the value: *p.
- In a declaration, * means "pointer": int *p; — in an expression it means "follow".
- *&x is x again: & and * undo each other.
- Print an address with %p: printf("%p", (void *) p);
Declaring and using pointers
- The type says what it points to: int *, double *, char *.
- int *p, *q; — every pointer name needs its own *.
- p = &x; makes p point to x; *p = 5; changes x.
- p = q; copies the address (both point to the same thing).
- *p = *q; copies the value (the pointers do not move).
NULL and wild pointers
- An uninitialised pointer is wild: it holds a random address.
- Dereferencing a wild pointer can change any memory or crash.
- NULL means "points nowhere" — give unused pointers this value.
- Always check if (p != NULL) before *p when p might be NULL.
- Dereferencing NULL crashes the program (segmentation fault).
Addresses and values side by side
Every line, explained.
#include <stdio.h>
int main(void)
{
int age = 20;
int *p = &age;
p holds the address of age.
printf("age = %d\n", age);
Prints age = 20
printf("&age = %p\n", (void *) &age);
An address, e.g. 0x7ffe5c1c (different on every run).
printf("p = %p\n", (void *) p);
The same address.
printf("*p = %d\n", *p);
Prints *p = 20
*p = *p + 1;
age becomes 21 — through the pointer.
printf("age = %d\n", age);
Prints age = 21
double d = 2.5;
double *dp = &d;
A pointer to double.
printf("%zu %zu\n", sizeof dp, sizeof *dp);
Prints 8 8 — the pointer and the double it points to.
int *none = NULL;
if (none != NULL)
false, so the next line is skipped.
printf("%d\n", *none);
return 0;
}
Spot the bug
Mistakes almost every beginner makes — and how to fix them.
Using an uninitialised pointer
int *p; *p = 5; // writes to a random address
int x; int *p = &x; *p = 5;
A pointer must point to real memory before you dereference it.
Forgetting the * for the second pointer
int *p, q; // q is an int!
int *p, *q;
The * belongs to each name, not to the type.
Assigning a value instead of an address
int x = 5; int *p = x; // p = address 5?!
int x = 5; int *p = &x;
A pointer needs an address. The compiler warns: "makes pointer from integer without a cast".
p = q when you meant *p = *q
p = q; // now both point to the same int
*p = *q; // copy the value
Without * you change where p points, not the int it points to.
Dereferencing NULL
int *p = NULL;
printf("%d", *p); // crash
if (p != NULL)
printf("%d", *p);
There is nothing at address 0. Check before following a pointer that may be NULL.
Check your understanding
Answer each question — you will see the explanation straight away.
int x = 4; int *p = &x; — what is *p?
*p is the int that p points to: x.
int x = 4; int *p = &x; *p = 10; — what is x now?
Writing through p writes x.
Which operator gives the address of a variable?
& is the address-of operator.
How big is a char * on a 64-bit system?
Every pointer stores an address: 8 bytes, whatever it points to.
Why initialise unused pointers to NULL?
if (p != NULL) is only possible when p is either valid or NULL.
Pointer Basics quiz
Test yourself: 10 questions, 70% to pass. Create a free account to take the quiz, save your progress and work towards the certificate.