Handout: Lecture 5 In-Class Exercises¶
Part A is pen-and-paper: read pointer code and draw the boxes and arrows. Part B is at the keyboard: pointers in real programs - walking an array, swapping through addresses, and returning two results with out-parameters. None of these repeats a Lecture 4 exercise; they drill the new move - handing a function an address so it can reach back to your variables.
Try each one yourself first; we will discuss in class, and the solutions are in a separate document afterward. Compile with warnings on:
Reminders that will keep you out of trouble today:
&xis the address ofx;*pis the thingppoints at. The&at a call site and the*inside the function are two halves of one handshake.p + 1steps by one element, not one byte - the pointer's type sets the stride.a[i]is the same thing as*(a + i).- A function gets a copy of each argument. To change a caller's variable, it needs the variable's address, not its value.
- Never dereference a pointer that points at nothing (
NULL) or at a variable that has already gone out of scope.
Set up¶
Part A - Read the pointers (pen and paper)¶
Exercise A1 - Trace the boxes and arrows¶
Work these out by hand; do not compile them yet. For the snippet below, draw a box
for x and a box for p, draw the arrow, and write down what each expression
evaluates to.
- After
int *p = &x;, what doesphold - a number, orx's value? - What is
*pjust before the third line runs? - After the third line, what is
x? What is*p? -
If
&xis the address2000, what doespprint with%p? What does&pprint - the same thing or something different? -
Stretch: add
int y = 7; p = &y;at the end. Redraw the arrow. Didxchange? What is*pnow?
Part B - Pointers at the keyboard¶
Exercise B1 - Sum an array with a walking pointer¶
Sum an integer array using a pointer that walks from the start to one past the
end. No [] anywhere in your loop - use *p and p++.
- Start
int *p = a;and loop whilep < a + n, doingtotal += *p;thenp++. a + nis the legal "one past the end" marker - you may compare against it, but never dereference it.- Stretch: print each element's address alongside its value with
%p, and confirm the addresses go up bysizeof(int)each step.
Exercise B2 - Swap through addresses¶
Write a function that swaps two ints in the caller, then prove it from main.
- Inside
swap, the values live at*aand*b; use a temporaryint t. - Call it as
swap(&x, &y);. The classic mistake is swapping the pointers themselves (int *t = a; a = b; b = t;) - that shuffles the local copies and leavesxandyuntouched. Make sure your stars are on the values. - Stretch: write
void swap_bad(int a, int b)that takes plainints, call it, and confirmxandydo not change. Explain in one sentence why.
Exercise B3 - Two results with out-parameters¶
A function returns one value with return. To hand back two, pass pointers for
it to fill. Write divide so the caller gets both the quotient and the remainder.
- In
main, declareint q, r;, calldivide(17, 5, &q, &r);, then printqandr. - Inside
divide, write the results through the pointers:*quotient = a / b;and*remainder = a % b;. - Stretch: this is exactly
scanf's pattern - it returns a status and sends your data back through the pointers you pass. Printdivide's results for a few input pairs and checkquotient * b + remainder == a.
Stretch - take it further¶
minmax with out-parameters¶
Combine Part B's two ideas: pass an array and two out-parameters, and report both extremes in a single pass.
- Seed
*loand*hifroma[0](the same "seed from an element" rule as before), then walk the rest, updating through the pointers. - The
constonais a promise thatminmaxonly reads the array - a good habit whenever a function should not modify what it is handed. - Call it with
int lo, hi; minmax(a, n, &lo, &hi);and print both. This returns two values from one pass, which a plainreturncannot do.