By the end of this lesson, cadets will be able to:
Complete before class. This is the hardest reading of the course so far. Plan extra time and read slowly.
| Source | Sections | Why |
|---|---|---|
| Beej-C | Chapter 5 (Pointers — Cower In Fear!) | All seven subsections. Read every one. |
| King, C Programming: A Modern Approach | Chapter 11 (Pointers) | Optional alternate explanation if Beej is not clicking |
& operator do?* operator do in a declaration vs in an expression?int *p, q;, what are the types of p and q?& example into a new file and run it. See an address come out on your machine.Pointers are the topic that separates “I’ve written some C” from “I can read any C codebase.” The mental model takes a beat to land. Once it does, every later topic in this block (pointer arithmetic, pass by pointer, malloc, structs with pointer fields) builds on the same picture. So we start slow and concrete: addresses, the & operator, pointer variables, dereferencing, and NULL. That’s it for today.
The Lesson 12 deck covers the mental model, the & operator, pointer declarations, the dereference operator, NULL, and the declaration gotcha. The slides set up the in-class lecture; the pointer walkthrough is where you practice each piece yourself.
Think of memory as a long row of numbered boxes, each holding one byte. The number on each box is its address. When you write int x = 42;, the compiler picks four consecutive boxes, writes the bits of 42 into them, and from then on the name x refers to those boxes. The address of the first box is the address of x.
A pointer is a variable whose value is an address. Same idea as a variable holding 42, except the number it holds is the location of some other variable. That’s it. Everything else in this lesson is syntax for asking “what is the address of this variable?” and “what is at the address this pointer holds?”
The & operator, when placed in front of a variable, gives you the address of that variable. The result is a pointer.
Print pointer values with %p. Cast to (void *) to keep the compiler quiet. The exact number you see will be different on every run; that’s the operating system handing your program a different stretch of memory each time, and it is normal.
You can recognize the address-of operator in any expression: a single & in front of a variable name. (Double && is “logical and” from CS110, totally unrelated.)
If this looks familiar, it should. Every scanf call back in Lesson 3 used the & operator: scanf("%d", &x). We described it then as a required syntactic ritual without explaining why. Now you can see it: scanf needs to know WHERE to store the value you type, and &x gives it that location. The full payoff lands at Lesson 14, when we look at how any function can use a pointer parameter to modify its caller’s variables.
A pointer declaration looks like a regular variable declaration with a * inserted before the name. The type before the * is the type of the thing the pointer will point at.
Read the declaration as “p is a pointer to an int.” The type matters: an int * can only point at ints. A char * can only point at chars. This becomes important when we get to pointer arithmetic in Lesson 13.
An uninitialized pointer is dangerous. It holds whatever garbage bits were in those bytes already. Treat that garbage as a random address and the program will crash (or worse, silently corrupt memory). Always assign a real address to a pointer before you use it. If you do not have one yet, assign NULL (see below).
When you have a pointer, the * operator (used in an expression, not a declaration) gives you access to the thing the pointer points at. You can read it, write it, do arithmetic with it; it acts as an alias for the original variable.
The two uses of * are the most confusing part of pointer syntax. In a declaration like int *p;, the * means “this variable is a pointer.” In an expression like *p = 100, the * means “follow the pointer and use the thing it points at.” Same character, different jobs. Context tells you which.
NULL is a special value that means “this pointer does not currently point at anything.” You can assign it to any pointer of any type. Use it to mark a pointer as “not ready yet” instead of leaving it uninitialized.
Dereferencing a NULL pointer crashes your program. The operating system specifically watches for reads and writes to address zero and kills your process. This is actually good news: a crash you can find in seconds is better than a silent memory corruption you might hunt for hours.
The habit that prevents this: any pointer that might be NULL gets checked with if (p != NULL) before dereferencing. You will see this pattern constantly in C code from Lesson 15 onward.
The asterisk binds to the name, not the type. When declaring multiple variables on one line, the * only applies to the name immediately after it. The line below declares one pointer and one plain int, despite what your eyes might tell you.
The cs210 style rule: in CS210, declare one variable per line. It is more typing but it eliminates this whole class of bug.
Pointer types must match. An int * cannot point at a double. The compiler will warn you and the bytes will be misinterpreted if you ignore the warning.
When you compile with -Wall -Werror (which you are, per the cs210 Makefile), the compiler will refuse to build. Fix the types; don’t cast the warning away.
Three things to do in class. Use the checklist to track your progress.
Twelve tasks across four sections. Type each C statement at the prompt. The terminal shows what the parser did; the right pane shows the current memory state with addresses and arrows from pointers to their targets.
Enter your name. It will appear on the completion screen so you can include it in your screenshot for the Blackboard reflection.