Introduction
Every variable lives at an address in memory. A pointer is a variable that holds an address. Pointers are what make C powerful, and what make it hard, so take this lesson slowly and watch the arrows.
Pointers are the idea that makes C both powerful and feared. They are simply addresses, and once you can see them as arrows from one box of memory to another, the mystery goes away.
How it works
& and *
#include <stdio.h>
int main(void) {
int x = 10;
int *p = &x;
printf("x = %d, *p = %d\n", x, *p);
*p = 20;
printf("x is now %d\n", x);
int y = 3;
p = &y;
*p = *p + 1;
printf("y is now %d\n", y);
return 0;
}&xmeans "the address of x".int *pdeclarespas a pointer to an int.*pmeans "the int that p points to". Reading*preads x; writing*p = 20changes x.
In the memory panel, p shows an arrow to x, and its value is x's address. On line 7, x changes even though the line never names it: that is the whole point of pointers.
NULL
NULL is a pointer to nothing. Following it with * is an error. Real C crashes with "segmentation fault"; StepVioz tells you which pointer was NULL:
#include <stdio.h>
int main(void) {
int count = 3;
int *p = &count;
printf("%d\n", *p);
p = NULL;
printf("%d\n", *p);
return 0;
}Syntax
int x = 5;
int *p = &x; // p holds the address of x
*p = 9; // x is now 9
if (p != NULL) {
printf("%d\n", *p);
}
Example
In the functions lesson, a function could not change the caller's variables. With pointers it can, because it gets their addresses:
#include <stdio.h>
void swap(int *a, int *b) {
int temp = *a;
*a = *b;
*b = temp;
}
int main(void) {
int x = 4, y = 9;
swap(&x, &y);
printf("x = %d, y = %d\n", x, y);
return 0;
}Step into swap: a and b are arrows back into main's frame, to x and y. *a = *b follows the arrows and changes main's variables. This is also why scanf needs &.
Line by line
swaptakes two addresses, in the pointersaandb.int temp = *a;saves the value thatapoints at.*a = *b;copies the second value into the first variable.*b = temp;puts the saved value in the second.mainpasses&xand&y, so the changes happen to its own variables.
Expected result
x = 9, y = 4
In the real world
Operating systems use pointers to manage all of a computer's memory, and device drivers use them to reach hardware directly. Null pointer errors are so common that their inventor, Tony Hoare, called them his "billion-dollar mistake".
Common mistakes
- Using a pointer that was never given an address:
int *p; *p = 5;. - Following a NULL pointer. Check
if (p != NULL)first. - Mixing up
p = q(now both point to the same place) and*p = *q(copy the value). - Returning the address of a local variable: it is gone once the function returns.
Best practices
- Initialise each pointer, to
NULLif there is nothing better. - Draw the boxes and arrows when you are unsure.
- Read declarations from the right:
int *pis a pointer to int.
Summary
A pointer holds an address. & gets an address, and * follows one. Passing addresses lets a function change its caller's variables, and NULL means a pointer has nowhere to go.
Quick check
Key takeaways
- &x is where x lives, and *p is what p points at.
- Passing an address lets a function change the caller's variable.
- Never follow a NULL or uninitialised pointer.
Practice problems for this lesson
My notes
Write down what you want to remember from this lesson. Notes are saved on this device as you type, and appear on your dashboard.