CSSE 132 Homework Review

Homework 4 Review: Pointers, Stack Frames, and Arguments

Review the written traces and the coding portion by keeping three things separate: a value, its address, and the storage that holds it. Allow about 10 minutes.

Why This Matters

Homework 4 connects C expressions to memory and ARM64 procedure calls. You explain which caller variables a function can change, count bytes in stack frames, and follow character pointers through argument strings. The coding portion then uses those string skills to interpret and validate decimal input.

Written Portion: A Copy of a Value or a Copy of an Address?

Core idea: C passes arguments by value. A function receives a copy of an integer or a copy of a pointer. Changing a copied integer leaves the caller's integer alone. Dereferencing a copied pointer can change the object whose address the caller supplied.

Worked Example: Two Different Assignments

void changeCopy(int n) { n = 14; }
void changeObject(int *p) { *p = 14; }

int score = 6;
changeCopy(score);       // score remains 6
changeObject(&score);    // score becomes 14

In the first call, only the function's local n changes. In the second, p holds a copy of score's address and *p names the caller's object. Reassigning p itself would change the local pointer, not the caller's object. Course descriptions may call this “pass by reference”; the C mechanism is passing an address by value.

Trace the Indices Before Naming a Loop

For a loop with index values 0, 2, 4 over {7, 1, -3, 8, 5}, a running total visits 7, -3, and 5: 0 → 7 → 4 → 9. The stride selects every second element starting at index zero. Name a function from its behavior, and name parameters from their roles: array, stride, and length tell you more than single letters.

The stride is in elements. C scales array[i] by the element size automatically. Do not multiply the index by 4 inside a C subscript just because an ARM64 integer load uses a byte address.

Written Portion: Allocated Bytes Are Not Always Used Bytes

A frame reserves space by moving sp toward lower addresses. Count the reservation separately from the distinct byte ranges occupied by saved values. On the course ARM64 system, an x register holds 8 bytes, a w register holds 4, and stack alignment is 16 bytes.

Worked Example: A Leaf Function's Frame

remember:
    sub sp, sp, 32
    str x0, [sp, 16]    // bytes 16–23: saved pointer
    str w1, [sp, 28]    // bytes 28–31: saved integer
    ldr w2, [sp, 28]    // reads the same slot
    add sp, sp, 32
    ret

This example allocates 32 bytes and uses 8 + 4 = 12 distinct bytes for saved values. Unused space is 32 − 12 = 20 bytes. A later load does not allocate another slot. Count the stored pointer as 8 bytes even if the pointed-to object is a 4-byte integer.

Also recognize stack adjustment inside a memory instruction: str x30, [sp, -32]! lowers sp by 32 before storing the 8-byte return address. ldr x30, [sp], 32 loads from the current address, then raises sp by 32.

bl writes the return address into x30. A function that calls another function must preserve its own return address when needed, then restore it before ret. Passing the address of a local integer requires an x register for the address; accessing that integer uses a w register.

Reading the supplied listing: the Homework 4 stack example omits ret after increment restores sp. Its displayed frame sizes can still be counted, but executing it literally would fall through into the next function. The C behavior assumes that increment returns normally.

Written Portion: Trace Each Argument Pointer Independently

For ./trace sun fog, argc is 3: the program name counts too. argv[0] points to "./trace", argv[1] to "sun", and argv[2] to "fog". Each is a null-terminated string.

Copying an entry into char *p[3] copies an address, not the text. Advancing p[j] then changes that local pointer entry while argv[j] retains its original address. A three-entry local pointer array only has room for indices 0 through 2.

Worked Example: Read One Character from Each String

Imagine three local pointers, initially at the starts of "./trace", "sun", and "fog". Read one character from each in order, print a newline, then advance each pointer once. Stop after the shortest string's length, which is 3.

Round 0: '.' + 's' + 'f' → .sf
Round 1: '/' + 'u' + 'o' → /uo
Round 2: 't' + 'n' + 'g' → tng

There are three newline operations, one per round, rather than one per character. The first pointer now points at the 'r' in "./trace". With that pointer, %c prints r when given the dereferenced character; %s prints race when given the pointer.

Subtracting the advanced pointer from its original pointer gives 3, the number of characters traversed. Pointer subtraction measures elements and is valid for positions within the same array, including its one-past-end position.

When tracing the homework, use the actual program-name string from the command shown. Include it in the shortest-length calculation. Keep commented-out statements out of your trace, and distinguish printed output from the integer returned by main.

Coding Portion: Validate Text Before Doing Arithmetic

Create add.c in your Homework 4 directory. The program takes exactly two decimal arguments, each from 0 to 99. The assignment forbids atoi. The inputs arrive as strings, so adding their first character codes is not numeric addition.

Worked Example: Decimal Place Values

For the text "42", first establish that both characters are decimal digits. Subtracting '0' turns '4' into 4 and '2' into 2. Place values give 4 × 10 + 2 = 42. A one-character string needs only its units digit.

An equivalent accumulation rule is value = value * 10 + digit: starting from zero, the intermediate values for "42" are 4 and 42. This explains the conversion without providing the complete homework program.

  1. Check the argument count before accessing argv[1] or argv[2]. Two supplied numbers require argc == 3.
  2. Check each complete string against the assignment's one- or two-digit nonnegative decimal format. An empty string, a sign, letters, or an extra character does not meet that format.
  3. Convert validated digits, then add the two integer values. Each input is at most 99, but their sum can be as large as 198.
  4. Choose the required output message and include its final newline. Avoid extra prompts or debugging output.

The required formats are Usage: ./add <num1> <num2>, Error: INPUT is not a number from 0 to 99., and Do you know that A + B = SUM?, with placeholders replaced by the relevant input or numbers. Match the PDF's spelling, spaces, punctuation, and newline.

Testing on the course Linux VM:

make add
./add 42 7
./test_add.sh

The provided script builds the program and compares output against support/test_add, stopping at the first failure. That helper is an ARM64 Linux executable. Also check boundaries and malformed strings manually: 0, 99, too many arguments, too few arguments, an empty argument, and a string containing a nondigit. A script pass is evidence, not a substitute for understanding validation. Submit add.c to Gradescope as the assignment directs.

Common Mistakes

Assignment to pointer confused with assignment through pointer

p = ... changes the pointer; *p = ... changes its target.

Every stack instruction counted as new storage

Count unique occupied byte ranges, not repeated reads and writes.

Program name omitted from the trace

argv[0] participates when the loop starts at zero.

Only the first input character checked

A leading digit does not make "4x" valid. Validate the whole string.

Quick Reference

Expression or ruleMeaning
&x / *pAddress of x / object at p's address.
Unused frame spaceAllocated bytes minus distinct occupied bytes.
argv[i] / argv[i][j]Argument string pointer / one character in that string.
%s / %cString starting at a pointer / a character value.
ch - '0'Numeric digit value after checking that ch is a decimal digit.

Check Yourself

  1. If a function receives int *p, does assigning *p = 11 change only the local pointer?
  2. A frame reserves 48 bytes, stores one x register and two w registers in separate slots, and reloads all three. How many bytes are used and unused?
  3. A pointer starts at "plane" and advances twice. What does %s print from there, and what is its difference from the original pointer?
  4. Why is checking only that argv[1][0] is a digit insufficient?
  5. What is argc for ./add 8 6, and what numeric sum should conversion produce?
Answers and Reasoning
  1. No. It writes 11 to the pointed-to object; the local pointer's address value stays the same.
  2. Used: 8 + 4 + 4 = 16 bytes. Unused: 48 − 16 = 32. Reloading does not occupy new bytes.
  3. ane; the difference is 2 characters.
  4. Later characters could be invalid, as in "8q", or the string could be too long. Check the complete input.
  5. 3, including the program name. The numeric sum is 14.