scanf has demanded an & since Lesson 3, and how to write functions that return more than one value. Two short labs cement the mechanics; the call-frame walkthrough in Section 5 makes it visible.
By the end of this lesson, cadets will be able to:
scanf require the address-of operator. (Outcome 2)Complete before class. Today's reading revisits two earlier chapters: Beej Chapter 5 (Pointers) for the function-argument section, and Beej Chapter 4 (Functions) for pass-by-value.
| Source | Sections | Why |
|---|---|---|
| Beej-C | Chapter 5 (Pointers): §5.3 (Dereferencing), §5.4 (Passing Pointers as Arguments) | The core mechanism for today. Read 5.4 carefully — this is the section where pointers stop being a curiosity and start being useful. |
| Beej-C | Chapter 4 (Functions): §4.1 (Passing by Value) — review | A short refresher. Today's lesson is built on the contrast between 4.1 and 5.4, so come in clear on both. |
| Beej-C | Chapter 5 (Pointers): §5.5 (The NULL Pointer) — review | Quick refresher from Lesson 12. Functions that take pointer parameters should check for NULL. |
int just by writing to its parameter?int *p, q; declaration trap. Twenty minutes max. Replay the Lesson 12 pointer walkthrough if you want a fast refresher.increment tries to modify its parameter. Before class, predict what the program prints. Then predict what changes if you rewrite it to take a pointer. If you can answer both without running code, you are ready for today.The Lesson 14 deck walks through pass-by-value, the limitation it imposes, how pass-by-pointer overcomes it, and the multiple-output-parameter pattern. The slides are the spine of the lecture; the call-frame walkthrough is where you watch the mechanics in motion.
Every function you have written so far receives copies of its arguments. The caller has variables; the function has parameters; the parameters are filled with the values from the caller's variables at the moment of the call. After that, they are independent.
The function received a copy. Modifying the copy did nothing to x back in main. This is pass-by-value, and it is the only thing C does. There is no other mode. Every parameter is a fresh local variable initialized from the argument.
If you want a function to modify a caller's variable, you cannot hand it the value. You have to hand it the location. Pass the address, and the function dereferences the pointer to read or write through it.
Notice the three changes from the value version. The parameter type became int *. The body dereferences with *p instead of using n directly. The call site uses &x to hand over the address.
Pass-by-value is still happening. The function receives a copy — but the copy is a copy of an address, and the address still points to x. Two pieces of paper now have the same address written on them. Either piece of paper can be used to find and modify the house.
A C function can return exactly one value. That is a real constraint. When a function naturally produces two or more results, you have two choices: return a struct (Lesson 18) or use pointer parameters as output channels. Today we use pointers.
The function returns void. Its actual outputs travel back through the three pointer parameters. This is the pattern Lab 2 uses today, and it is one of the most common things you will see in real C code: an input value goes in, several derived results come out through pointers.
Since Lesson 3 you have been writing scanf("%d", &x) without a real explanation for the &. We called it a syntactic ritual. Now the ritual ends.
scanf reads a value from input and has to store it somewhere — namely, in one of your variables. To store into your variable, it needs to know the variable's address. So it takes a pointer parameter, and you have to give it an address. That is what & does.
If you wrote scanf("%d", x) by mistake, you would hand scanf the value of x (uninitialized garbage), it would treat that garbage as an address, and it would try to write to that random memory location. The result is undefined behavior and, usually, a crash. The compiler will warn you with -Wall enabled. Read the warning.
Exception: when you read a string with %s, you pass the array name itself with no &. That is because an array name already is an address — the array-pointer duality from Lesson 13. Same mechanism, just a different surface.
Every function call draws a boundary. On the caller's side: local variables, the caller's frame. On the callee's side: parameters and the callee's locals. The question pass-by-pointer answers is: what crosses that boundary?
With pass-by-value, only the value crosses. The caller's variable is invisible to the callee; the caller's state is protected. With pass-by-pointer, an address crosses, and through that address the callee can reach back into the caller's frame and modify what is there.
This is a design decision, not just a syntactic one. When you write a function, decide first what it needs: does it need to know a value, or does it need to be able to change a value? The answer chooses the parameter type. Pass-by-value when the function should compute and return. Pass-by-pointer when the function legitimately needs to modify what the caller owns — or when it needs to return more than one result.
Four things in class today. Use the checklist to track your progress.
Nine tasks across three sections. Watch two memory frames side-by-side as functions are called: the caller's frame on the left, the callee's frame on the right. See pass-by-value copying values and pass-by-pointer reaching back through arrows.
Enter your name (first and last). It will appear on your completion screen so the screenshot is linked to you.