A pointer holds an address
A pointer in C is a variable that holds the address of another variable. Pointers let a function change its caller's data. They also let a program walk along memory. Most students find them the hardest part of C.
Think of a delivery note. It is not the parcel, it says where the parcel is. A pointer is that note.
By the end of this lesson
Note
I can read and write C code that uses pointers.
Key words
| Word | What it means | Example |
|---|---|---|
| Pointer | a variable that holds an address | |
| Address-of | the & operator, which gives where a variable is | &stock |
| Dereference | the * operator, which follows a pointer to its value | *p |
| Pointer arithmetic | adding to a pointer to move by whole elements | p + 1 |
| NULL | the pointer value that points at nothing | |
| Pass by value | giving a function a copy of a value |
The cells students fill in are left blank in this preview.
A pointer stores where a value lives
Write int *p = &stock; and p holds the address of stock. The & means "the address of". Write *p and C follows that address to the value. This is dereferencing.
Writing *p = 9; changes stock itself, because p points at it. A pointer set to NULL points at nothing, and following it crashes the program.
Worked example with invented addresses
| Name | Address | Holds |
|---|---|---|
| stock | 100 | 7, then 9 after *p = 9 |
| p | 200 | 100, the address of stock |
| *p | 100 (reached through p) | The same value as stock |
The cells students fill in are left blank in this preview.
Change a variable through its pointer
#include <stdio.h>
int main(void) {
int stock = 7;
int *p = &stock; // p holds the address of stock
*p = 9; // follow p and store 9 there
printf("stock is %d\n", stock);
printf("same place: %d\n", p == &stock);
return 0;
}
Write and build the pointer program
printf '%s\n' '#include <stdio.h>' 'int main(void) {' ' int stock = 7;' ' int *p = &stock;' ' *p = 9;' ' printf("stock is %d\n", stock);' ' printf("same place: %d\n", p == &stock);' ' return 0;' '}' | gcc -Wall -x c - -o ptrShown here, not run. Create a free account to press Run and type it into your own lab’s terminal.
Run it and read stock
./ptrShown here, not run. Create a free account to press Run and type it into your own lab’s terminal.
Adding to a pointer moves by whole elements
If p points at the first item of an int array, p + 1 points at the second. C adds the size of one int, four bytes, and not one byte.
So *(p + 2) is the third item. Taking two pointers apart, (p + 3) - p, gives a count of elements, not bytes.
Worked example: an int array at address 100
| Expression | Address | Value |
|---|---|---|
| p | 100 | 10 |
| p + 1 | 104 | 20 |
| p + 2 | 108 | 30 |
| p + 3 | 112 | 40 |
The cells students fill in are left blank in this preview.
Write and build the arithmetic program
printf '%s\n' '#include <stdio.h>' 'int main(void) {' ' int prices[4] = {10, 20, 30, 40};' ' int *p = prices;' ' printf("%d %d\n", *p, *(p + 2));' ' printf("bytes between: %ld\n", (char *)(p + 2) - (char *)p);' ' printf("elements between: %ld\n", (p + 3) - p);' ' p = p + 1;' ' printf("now %d\n", *p);' ' return 0;' '}' | gcc -Wall -x c - -o arithShown here, not run. Create a free account to press Run and type it into your own lab’s terminal.
Print values, bytes and elements
./arithShown here, not run. Create a free account to press Run and type it into your own lab’s terminal.
A common mistake
Warning
Many people think p + 1 adds one byte to the address. It adds the size of the type pointed to. For an int * that is four bytes, and for a char * it is one. Cast to char * when you really want bytes.
A function changes data through a pointer
C passes arguments by value: the function gets a copy. Changing the copy leaves the caller's variable alone.
To let a function change the original, pass its address. The function follows the pointer and changes the real variable. The program below calls both ways on two variables that start equal.
Write and build the two functions
printf '%s\n' '#include <stdio.h>' 'void bump(int *n) { *n = *n + 1; }' 'void bump_copy(int n) { n = n + 1; }' 'int main(void) {' ' int a = 5, b = 5;' ' bump(&a);' ' bump_copy(b);' ' printf("a %d, b %d\n", a, b);' ' return 0;' '}' | gcc -Wall -x c - -o byrefShown here, not run. Create a free account to press Run and type it into your own lab’s terminal.
Compare the copy and the pointer
./byrefShown here, not run. Create a free account to press Run and type it into your own lab’s terminal.