Kodewick
Lesson 15 of 30Contents

Addresses and pointers

Lesson 15 of 30 · Part 3 · Pointers · about 15 minutes

So far we have used variables only by their names. But every variable lives somewhere in memory, and that place has a number: its address. A pointer is a variable that holds an address. Pointers are the hardest step in C, so in this lesson, press Step often and watch where each arrow points.

Where a variable lives

Put & in front of a variable to get its address. To print an address, use the format specifier %p (and write (void *) in front, which is what %p expects).

1int score = 90;2printf("score  = %d\n", score);3printf("&score = %p\n", (void *)&score);

On one computer, one run printed this:

score  = 90
&score = 0x7ffd5e8a1c4c

An address is a number written in hexadecimal. It changes from computer to computer and from run to run: run these lines yourself and you will get a different one. There is nothing to remember about the number itself. Remember only this: every variable has an address, and & gets it.

Two variables can hold the same value, but each one has its own address. == works on addresses too:

main.c
1#include <stdio.h>2 3int main(void) {4    int a = 5;5    int b = 5;6    printf("a == b: %d\n", a == b);7    printf("&a == &b: %d\n", &a == &b);8    return 0;9}
Output
a == b: 1
&a == &b: 0

1 means true and 0 means false (lesson 5). a and b are equal, but they live in two different places.

Now you can read scanf("%d", &age) from lesson 3: &age is the address of age. scanf needs to know where age is in memory so it can put the number there.

Pointers: variables that hold addresses

Read int *p as "p is a pointer to an int". Store &score in it and p points to score. A * in front of a pointer means "follow the address to the variable", so *p = 100 changes score.

main.c
1#include <stdio.h>2 3int main(void) {4    int score = 90;5    int *p = &score;6    *p = 100;7    printf("%d\n", score);8    return 0;9}
Output
100

Press Step: p is drawn as an arrow pointing at score. After line 6, the score at the end of the arrow is 100, though line 6 never mentions score.

A pointer's type says what it points to. An int * points to an int, a double * to a double, a char * to a char:

main.c
1#include <stdio.h>2 3int main(void) {4    double price = 4.50;5    char grade = 'B';6    double *pp = &price;7    char *pg = &grade;8    *pp = *pp * 2;9    *pg = 'A';10    printf("%.2f %c\n", price, grade);11    return 0;12}
Output
9.00 A

Two different stars

* shows up in two places, with two meanings:

You writeWhereIt means
int *pin a declarationp is a pointer to an int
*pwhen you use itthe variable p points to
&xwhen you use itthe address of x

So int *q = &n; declares q and stores the address of n in it. It does not put anything into *q. After that, *q reads n:

main.c
1#include <stdio.h>2 3int main(void) {4    int n = 7;5    int *q = &n;6    printf("n = %d, *q = %d\n", n, *q);7    n = 8;8    printf("n = %d, *q = %d\n", n, *q);9    return 0;10}
Output
n = 7, *q = 7
n = 8, *q = 8

q doesn't hold a copy of 7. It holds where n is, so when n changes, *q sees the new value.

Guess first

What does this print?

1#include <stdio.h>2 3int main(void) {4    int a = 1;5    int *p = &a;6    *p = *p + 5;7    printf("%d\n", a);8    return 0;9}

Pointing somewhere else

A pointer is a variable, so you can give it a new address. Assign to p (no star) to change where it points; assign to *p to change what is there.

main.c
1#include <stdio.h>2 3int main(void) {4    int apples = 3;5    int pears = 5;6    int *p = &apples;7    *p = 4;8    p = &pears;9    *p = 6;10    printf("apples %d, pears %d\n", apples, pears);11    return 0;12}
Output
apples 4, pears 6

Press Step and watch the arrow: first it points at apples, and on line 8 it swings over to pears. Each *p = ... changes whichever variable the arrow points at right then.

Pointers that point nowhere

A pointer that was declared but never given a value holds a garbage address. Following it means reading or writing some random place in memory:

main.c
1#include <stdio.h>2 3int main(void) {4    int *p;5    *p = 5;6    printf("%d\n", *p);7    return 0;8}
Output
use of uninitialized value

What happened: Stopped at line 5. A variable was used before it was given a value. In real C it would hold garbage, different on every run.

On a real computer, a program like this sometimes crashes and sometimes seems fine, which makes it one of the hardest bugs to find. Our engine stops on the line where it happens and tells you. Press "see how it went wrong".

When you don't know yet what a pointer should point to, set it to NULL, a special value that means "points to nothing". Check p != NULL before you use it:

main.c
1#include <stdio.h>2 3int main(void) {4    int stock = 12;5    int *p = NULL;6    if (p != NULL) {7        printf("before: %d\n", *p);8    }9    p = &stock;10    if (p != NULL) {11        printf("after: %d\n", *p);12    }13    return 0;14}
Output
after: 12

Tip: Every pointer should get a value when you declare it: either the address of something, or NULL. Lesson 18 goes through what else can go wrong with pointers.

Practice

Write the code, then press Check. A hint costs nothing; the answer is there when you need it.

Exercise 1

Raise the price

Don't write price directly: add 10 to it through p. The program should print price = 60.

It should print
price = 60
exercise1.c
1#include <stdio.h>2 3int main(void) {4    int price = 50;5    int *p = &price;6    // add 10 to price through p7 8    printf("price = %d\n", price);9    return 0;10}
Output
Press Run or Ctrl+Enter
Exercise 2

Point somewhere else

p points to a. Make it point to b instead, then set b to 0 through p. The program should print a = 3, b = 0.

It should print
a = 3, b = 0
exercise2.c
1#include <stdio.h>2 3int main(void) {4    int a = 3;5    int b = 8;6    int *p = &a;7 8    printf("a = %d, b = %d\n", a, b);9    return 0;10}
Output
Press Run or Ctrl+Enter
Exercise 3

Fix it

This program uses a pointer that was never given a value, and the engine stops. Change one line so it prints Temperature: 25.

It should print
Temperature: 25
exercise3.c
1#include <stdio.h>2 3int main(void) {4    int temp = 21;5    int *p;6    *p = 25;7    printf("Temperature: %d\n", temp);8    return 0;9}
Output
Press Run or Ctrl+Enter

What you learned

  • Every variable has an address in memory; &x gives the address of x, and %p prints it (it differs from run to run).
  • int *p = &x; stores the address of x in p: p points to x.
  • *p is the variable p points to: you can read it and change it.
  • In int *p the star declares a pointer; in *p it follows the pointer.
  • p = &y; changes where p points; *p = 5; changes what is there.
  • Never use a pointer that has no value. When you don't know yet, set it to NULL and check before using it.