Loading
0x90Lesson 10 of 20

Pointers

The idea C is famous for: a variable that holds the address of another. Less scary than its reputation.

16 min 6-question quiz 1 code exercise
By the end of this lesson you can
  • Explain what an address and a pointer are
  • Use & to take an address and * to follow a pointer
  • Write a function that changes its caller's variables

Memory is one long row of bytes, and every byte has a number: its address. Every variable lives at some address. A pointer is simply a variable whose value is an address - it "points at" another variable. That is the whole idea; the rest is syntax.

Try it

Up to 15 XP

Follow the address

Solve two memory missions by choosing what p points to, then writing through *p. Watch the values in the address cards and avoid dereferencing NULL.

Mission 1: Make x = 8 while y stays 12

Score 0/2

Illustrative addresses only; real addresses vary between runs. This model never dereferences an invalid pointer.

0x100x7
0x104y12
0x108pNULL

Choose an address for p before writing through it.

Addresses with &

The & operator gives you the address of a variable. (You have already used it with scanf: &number told scanf where to write.) Addresses print with %p, and they will be different every time you run the program:

address.c
1#include <stdio.h>
2
3int main(void) {
4    int age = 30;
5    printf("age holds %d\n", age);
6    printf("age lives at %p\n", (void *)&age);
7    return 0;
8}

Declaring and following a pointer

pointer.c
1#include <stdio.h>
2
3int main(void) {
4    int age = 30;
5    int *p = &age;     // p holds the address of age
6
7    printf("%d\n", *p);  // follow p: prints 30
8
9    *p = 31;           // write through p
10    printf("%d\n", age); // age changed: prints 31
11    return 0;
12}
Output
30
31

Two different jobs for * - this is where most confusion comes from:

  • In a declaration, int *p means "p is a pointer to an int".
  • In an expression, *p means "the thing p points at" - this is called dereferencing.

So *p = 31; does not change p at all. It goes to the address stored in p and writes 31 there - into age.

Why pointers: changing the caller's variables

Remember that functions get copies of their arguments. To let a function change the caller's variable, pass its address instead - the function gets a copy of the address, and a copy of an address still leads to the same place:

swap.c
1#include <stdio.h>
2
3void swap(int *a, int *b) {
4    int temp = *a;
5    *a = *b;
6    *b = temp;
7}
8
9int main(void) {
10    int x = 1, y = 2;
11    swap(&x, &y);
12    printf("x = %d, y = %d\n", x, y);
13    return 0;
14}
Output
x = 2, y = 1

This is exactly how scanf works, and it is also how C functions "return" more than one value: the caller passes addresses for the results to be written into.

NULL

NULL is a special pointer value meaning "points at nothing". It is useful as a "no result" marker, and it is what you should set a pointer to when it has nothing valid to point at yet. Dereferencing NULL is undefined behavior - usually an immediate crash ("segmentation fault"). Check before you follow a pointer that might be NULL.

Pointers and arrays

An array name used in an expression turns into ("decays to") a pointer to its first element - which is why passing an array to a function passes an address. You can do pointer arithmetic: p + 1 points at the next element, not the next byte, because the compiler knows the element size. In fact, a[i] is defined as *(a + i).

walk.c
1#include <stdio.h>
2
3int main(void) {
4    int values[] = {10, 20, 30};
5    int *p = values;   // same as &values[0]
6
7    printf("%d\n", *p);
8    printf("%d\n", *(p + 1));
9    printf("%d\n", p[2]);
10    return 0;
11}
Output
10
20
30

Key takeaways

  • A pointer holds an address. &x is the address of x; *p is the value p points at.

  • Pass addresses (swap(&x, &y)) when a function must change its caller's variables.

  • Initialize pointers (to a real address or NULL), never dereference NULL, and never keep the address of a local variable after its function returns.

Lesson quiz

6 questions · pass with 5 correct · up to 50 XP

Passing this quiz completes the lesson and keeps your streak going. Questions you miss come back in review sessions later.

Practice: write C

These run for real. Write the program, press Run tests, and read what the compiler tells you - learning to read compiler messages is half of learning C.

Exercise 1

Two results at once

+25 XP

Write void min_max(const int values[], int length, int *min, int *max) that stores the smallest and largest element through the two pointers. main reads a count and that many numbers, calls your function, and prints the results.

For 5 then 3 9 -2 7 4, the output is min=-2 max=9.

  • Mixed values
  • One value
main.c
Loading editor…

Your code is compiled with gcc 14 (-Wall -Wextra) and run on Compiler Explorer (godbolt.org), a free public service.

Questions about this lesson

Stuck? Ask. Figured something out? Share it. Explaining is one of the best ways to learn.

Loading posts…