CMSC 14300: Practice Set 4 - Pointers and Dynamic Memory¶
Practice for the material in Week 3: pointers, pointer arithmetic, passing pointers
to functions, the stack-vs-heap distinction, and heap allocation with
malloc/free. None of these repeats a lecture or homework exercise; together
they drill the new moves - handing a function an address, walking a pointer, and
owning heap memory. This is good preparation for the next quiz.
Work in a fresh directory and compile everything with warnings on. Link
<stdlib.h> for malloc/free:
mkdir -p ~/cmsc14300/lec05-pset && cd ~/cmsc14300/lec05-pset
clang -Wall -Wextra -std=c17 problem1.c -o problem1
If your compiler prints a warning, treat it as something to fix - warnings are the compiler trying to help you, and the warning about "returning the address of a local" in particular is one you want to listen to.
Problem 1 - Rotate three values through pointers¶
Write a function that rotates three ints in the caller: a takes b's
value, b takes c's, and c takes a's old value. The whole point is that the
change must be visible back in main, so the function takes addresses.
- Save one value in a temporary first, then shuffle through the pointers - the same idea as a two-way swap, with one more step.
- Call it as
rotate3(&x, &y, &z);. Ifx,y,zdo not change, you swapped the pointers instead of the values they point at - put your stars on the values (*a,*b,*c).
Problem 2 - Split a duration with out-parameters¶
A function returns one value, but here you need three. Use out-parameters: pass pointers for the function to fill with hours, minutes, and seconds.
*h = total_seconds / 3600;then reduce the remainder for minutes and seconds. The/and%operators do all the work.- In
main, declareint h, m, s;, callsplit_time(3661, &h, &m, &s);, then print the three. Check a few values by hand:3661 = 3600 + 60 + 1.
Problem 3 - Sum a sentinel-terminated array by walking a pointer¶
Some arrays carry an end marker instead of a separate length - the same idea as
a string's '\0'. Here the marker is a -1. Write a function that sums everything
before the -1, using only pointer arithmetic - no [] and no length passed
in.
- Walk a pointer:
const int *p = a;then loopwhile (*p != -1), doingtotal += *p;andp++. Stop when the dereferenced value is the sentinel. - This is exactly the "walk to the terminator" loop from strings, with
-1playing the role of'\0'and a pointer instead of an index. - Check your understanding: why does this function not need an
nparameter, when Lecture 4'ssum(int a[], int n)did? What plays the role thatnplayed?
Problem 4 - Read an unknown count into a heap buffer, then print it reversed¶
You do not know how many numbers are coming until the user tells you. Read the
count n first, allocate a heap array of exactly that size, fill it, print the
values in reverse order, and free it. This is the array whose size is decided
at run time - a fixed int a[100] could not adapt to n.
- Read
n, thenint *a = malloc(n * sizeof(int));. CheckaagainstNULLbefore using it. - Fill with a
scanf("%d", &a[i])loop over0 .. n-1, then print with a second loop runningifromn - 1down to0. - Finish with exactly one
free(a);. Onemalloc, onefree. - The new thing here is that
ais a heap block sized by the user at run time, not a constant baked into the program. Indexing it (a[i]) works exactly as on a stack array.
Problem 5 - Build and return a heap array¶
Write a function that allocates an array of the first n even numbers on the
heap and returns it. The caller uses it and frees it. This is the safe way to hand
back an array from a function - heap memory outlives the call, a local array does
not.
- Inside
evens:malloc(n * sizeof(int)), check forNULL(returnNULLon failure), filla[i] = 2 * i;, andreturn a;. - In
main: callevens(5), check the result, print the values, thenfreeit -mainowns the block now. The function allocates; the caller frees. - Check your understanding: what goes wrong if
evensinstead declares a localint a[100];and returnsa? Which lifetime rule does that break, and what does the compiler say about it?
Self-check¶
You're ready for the upcoming quiz material if you can, without looking it up:
- Explain what
&and*do, and why writing through a pointer changes the original variable. - State why C functions cannot change a caller's variable unless they are given its address, and how out-parameters return more than one value.
- Say what
a[i]means in terms of pointer arithmetic, and whyp + 1advances by one element rather than one byte. - Describe the difference between the stack and the heap: who controls each one's lifetime, and when you need the heap.
- Write the
malloc/check/use/freesequence from memory, and name the two bugs that come from gettingfreewrong (a leak and a dangling pointer). - Explain why a function may return heap memory but never the address of a local.