Easier to read with cream paper, a tint, more contrast or larger text? Choose your colours and text, once, for every page.

Free lesson

How pointers work in C

After this lesson: I can read and write C code that uses pointers.

55 min lesson6 commandsCompilers and computer architecture lab: gcc, flex, bison and RISC-V in one VM

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

WordWhat it meansExample
Pointera variable that holds an address
Address-ofthe & operator, which gives where a variable is&stock
Dereferencethe * operator, which follows a pointer to its value*p
Pointer arithmeticadding to a pointer to move by whole elementsp + 1
NULLthe pointer value that points at nothing
Pass by valuegiving 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

NameAddressHolds
stock1007, then 9 after *p = 9
p200100, the address of stock
*p100 (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

Code: c
#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

Command
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 ptr

Shown here, not run. Create a free account to press Run and type it into your own lab’s terminal.

Run it and read stock

Command
./ptr

Shown 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

ExpressionAddressValue
p10010
p + 110420
p + 210830
p + 311240

The cells students fill in are left blank in this preview.

Write and build the arithmetic program

Command
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 arith

Shown here, not run. Create a free account to press Run and type it into your own lab’s terminal.

Print values, bytes and elements

Command
./arith

Shown 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

Command
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 byref

Shown 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

Command
./byref

Shown here, not run. Create a free account to press Run and type it into your own lab’s terminal.

About this lab and its source: Compilers and computer architecture lab: gcc, flex, bison and RISC-V in one VM

Teaching a class? Set this module for your students with a teacher guide, marked assignments and a lab for every student.