Solutions: Lecture 5 In-Class Exercises¶
Solutions to the Lecture 5 in-class exercises. Try each exercise yourself before reading these.
Part A - Read the pointers (pen and paper)¶
Exercise A1 - Trace the boxes and arrows¶
pholds a number: the address ofx(here2000). It does not hold10; it holds where the10lives.- Just before the third line,
*pis10- followptoxand read it. *p = *p + 5;reads10, adds5, and writes15back throughpintox. Soxis15, and*pis15- they are two names for the same box.-
pprints2000(the address ofx).&pprints something different: the address of thepbox itself.pand&pare not the same - one is wherexis, the other is wherepis. -
Stretch: after
int y = 7; p = &y;, the arrow now points aty.xis untouched (still15) - reassigningponly moves the arrow, it does not copy values.*pis now7.
Part B - Pointers at the keyboard¶
Exercise B1 - Sum an array with a walking pointer¶
#include <stdio.h>
int main(void) {
int a[] = {10, 20, 30, 40, 50};
int n = 5;
int total = 0;
for (int *p = a; p < a + n; p++) {
total += *p;
}
printf("sum = %d\n", total);
return 0;
}
int *p = a;starts the pointer ata[0]- the array name decays to that address, so no&is needed.p < a + nstops the loop exactly at the one-past-the-end address. We compare against it but never write*pthere.- This is the index loop
for (int i = 0; i < n; i++) total += a[i];with the address moving instead of the index.*phere is*(a + i)there. - Stretch (addresses):
printf("%p: %d\n", (void *) p, *p);inside the loop prints each slot's address; they rise bysizeof(int)(typically 4) each step, which is whyp++lands on the next element.
Exercise B2 - Swap through addresses¶
#include <stdio.h>
void swap(int *a, int *b) {
int t = *a;
*a = *b;
*b = t;
}
int main(void) {
int x = 3, y = 7;
printf("before: x = %d, y = %d\n", x, y);
swap(&x, &y);
printf("after: x = %d, y = %d\n", x, y);
return 0;
}
- Every read and write inside
swapgoes through a*, so it lands on the caller'sxandy, not on local copies. The temporarytis a plainintholding one value mid-swap. - The bug to avoid - swapping the pointers themselves:
void swap_wrong(int *a, int *b) {
int *t = a; a = b; b = t; /* shuffles the local copies of the addresses */
}
This rearranges swap's private pointer variables and returns; x and y never
move. The fix is to operate on *a and *b, the things pointed at.
- Stretch (swap_bad): a version taking int a, int b swaps its own copies and
returns, so x and y are unchanged - C passed the values, not the variables.
Exercise B3 - Two results with out-parameters¶
#include <stdio.h>
void divide(int a, int b, int *quotient, int *remainder) {
*quotient = a / b;
*remainder = a % b;
}
int main(void) {
int q, r;
divide(17, 5, &q, &r);
printf("17 / 5 = %d remainder %d\n", q, r);
return 0;
}
- The caller owns
qandr; it passes their addresses sodividecan fill them in. After the call,qandrhold the results. - This is the standard C way to return more than one value, since
returnhands back only one.scanfworks the same way: a status comes back throughreturn, your data through the pointers. - Stretch (the check):
q * b + r == ashould hold for every pair, e.g.3 * 5 + 2 == 17. It is the definition of integer division and remainder.
Stretch¶
minmax with out-parameters¶
#include <stdio.h>
void minmax(const int *a, int n, int *lo, int *hi) {
*lo = a[0];
*hi = a[0];
for (int i = 1; i < n; i++) {
if (a[i] < *lo) {
*lo = a[i];
}
if (a[i] > *hi) {
*hi = a[i];
}
}
}
int main(void) {
int a[] = {42, 17, 99, 3, 56, 8};
int n = 6;
int lo, hi;
minmax(a, n, &lo, &hi);
printf("lo = %d, hi = %d\n", lo, hi);
return 0;
}
- Both results travel back through
*loand*hi, so one pass returns two values - something a singlereturncannot do. - Seed
*loand*hifroma[0], then start the loop ati = 1. Seeding from an actual element (not0) keeps it correct for all-negative arrays. const int *asaysminmaxonly reads the array. If you accidentally wrotea[i] = ..., the compiler would reject it - a cheap guard worth using whenever a function should not modify its input.