Class 6 — Thursday, September 10

A function the compiler cannot find, though it is right there in the file. Then one program split across three files.
This page is not the assignment

Work through this page in class, with me in the room. You do not submit it and it is not graded.

A3 goes out at the end of today and that is the one you submit. Today is the practice for it.

1 Predict-then-run

Make the file yourself, call it triple.c, and copy-paste the program below into it.

#include <stdio.h>

int main() {
    printf("%d\n", triple(5));
}

int triple(int n) {
    return n * 3;
}

There is nothing missing. Every brace is closed, every semicolon is there, and triple is defined in the same file as the call to it.

Do not compile it yet. First write your prediction in your Brightspace Journal — two minutes, and a guess counts:

  1. Does gcc -Wall triple.c -o triple compile it?
  2. Whether it compiles or not, what does it print?

Now compile it, and read every word gcc printed. One word in particular: is it warning or is it error?

Then add to the same Journal note what actually happened, and why you think it did.

2 The ladder

Note: If you have been stuck for three minutes, put your hand up.

Pairs, one keyboard between two people. The person not typing reads this page out loud and says what to type next, and you swap who types at every rung.

Start a fresh directory for today, e.g. ~/cmsc240/class-6/. Some of the file names are ones you already used last week, and the last rung builds everything in the directory at once.

Open the design recipe in a second tab and leave it there. It is the order to write a function in — signature first, body last — and every rung below is a function. Do not read it through now; read it tonight, before you start A3.

2.1 Rung 1 — max.c, three ways

Write int max(int a, int b) returning the larger of two numbers, and a main that prints max(6, 10).

Then build it three times, in this order, compiling with gcc -Wall max.c -o max after each:

  1. Definition below main. This is the one that goes wrong — it is the program from the top of this page with a different name.
  2. Definition moved above main.
  3. Definition back below main, and this line added above it:
int max(int a, int b);

That last one is a prototype: the first line of the function, with a semicolon where the body would be. It tells the compiler the name, what goes in and what comes out, and nothing about how.

Done when you can say which of the three worked and what the compiler needed. Short note on it in notes.txt

2.2 Rung 2 — digits.c, with the work given a name

Take last week’s digit-counting loop and put it inside int count_digits(int n). main reads a number with scanf and prints the count.

No printf and no scanf inside count_digits. It takes a number and returns a number, and that is all it does.

Done when it prints 5 for 90210 and 1 for 7, and you have not recompiled between the two.

2.3 Rung 3 — one program, three files

Same two functions. Nothing new gets computed. What changes is where the code lives.

numbers.h — the prototypes, and nothing else:

// Include guard: magic that stops this file being pasted in twice.
// Name it after the file:  numbers.h -> NUMBERS_H
#ifndef NUMBERS_H
#define NUMBERS_H

int max(int a, int b);
int count_digits(int n);

#endif

Copy the two comment lines as well. You are taking the guard on trust today — the reason it works is Rung 5.

numbers.c — the two definitions, no main, and #include "numbers.h" at the top. The quotes matter: angle brackets mean a header that came with the system, quotes mean a file of mine, sitting in this directory.

main.c — only main, opening with both #include <stdio.h> and #include "numbers.h". Call both functions and print the results.

Build it with both files named:

gcc -Wall main.c numbers.c -o numbers

Done when ./numbers runs and you can see both functions in its output.

2.4 Rung 4 — leave a file out

Run this, with numbers.c missing from the line:

gcc -Wall main.c -o numbers

Read the message. It does not name a line of your code, and that is the interesting part — nothing is wrong with any line of your code.

Done when you can say out loud what the message was, and what it means that gcc got far enough to complain about this at all.

2.5 Rung 5 — watch #include do its work

#include is not import. It is a paste: the named file’s contents are dropped in where that line was, before the compiler sees anything. You can stop gcc right after the pasting and look:

gcc -E main.c > main.i

Open main.i. Your main.c is maybe twenty lines. This is not.

Done when you can find your two prototypes in main.i and say where the rest of it came from.

3 If you have already finished

3.1 Add a third function

char letter_grade(int score), returning 'A' through 'F' on last week’s boundaries. It goes in all three files: a prototype in numbers.h, the definition in numbers.c, a call in main.c. Character constants use single quotes, and printf prints one with %c.

Doing it once by hand is the point — three files, three edits, and you will be doing exactly this every time a program grows a function from now on.

3.2 Then write a Makefile

In the same directory, a file called exactly Makefile:

numbers: main.c numbers.c numbers.h
	gcc -Wall -o numbers main.c numbers.c

clean:
	rm -f numbers

The whitespace in front of gcc and rm has to be one tab character, not spaces. It looks identical on screen either way, and with spaces make says missing separator and stops. In nano the Tab key gives you a real tab.

Then run make, then make clean, then make again. Then run make twice in a row without changing anything, and read what it says the second time.

This is Tuesday’s topic and you have just done it, which is the best possible position to be in on Tuesday.

4 Before you leave

Today’s work is the start of A3, so it is worth keeping.

Your home folder persists, so these files will still be here next time you sit at this machine. Only this one, though — a different seat is a different home folder.

So put today’s files on Brightspace before you go — Assignment 3 is up already. It keeps the latest version, so uploading a half-finished numbers.c costs you nothing and replacing it on Tuesday is one click.

Both of you, not just whoever typed last. One keyboard means the files are on one machine and in one person’s home folder. So: the person who typed submits, signs out of Brightspace, and then the other one signs in on that same machine and submits the same files. Two identical submissions from a pair is correct and expected.