CS210 · Block 4 · Lesson 20

Organizing Multi-file C Code

Headers and .c files · The preprocessor · Include guards · static and visibility · Reading linker errors
At a glance: Your code has been growing. Today we split it across files. You learn the rules the preprocessor and linker care about, why headers look the way they do, and how to read the linker errors that show up when you get the rules wrong. The header file walkthrough in Section 5 makes the rules concrete; the lab applies all of it to a flight-statistics utility.
Contents
  1. Lesson Objectives
  2. Assigned Readings
  3. Pre-Class Work
  4. Lesson Materials and Overview
  5. In-Class Work
  6. After Class
1. Lesson Objectives

By the end of this lesson, cadets will be able to:

  1. Organize a C program across multiple source and header files, with each function in the right place. (Outcomes 2, 4)
  2. Apply include guards to prevent duplicate inclusion. (Outcome 4)
  3. Use preprocessor directives appropriately: #include, #define, conditional compilation. (Outcome 4)
  4. Apply static at file scope to limit visibility of helpers. (Outcomes 2, 4)
  5. Read four common linker errors and map each to its cause. (Outcome 3)
  6. Write at least three self-tests, each covering a different edge case, in tests.c. (Outcomes 3, 7)
2. Assigned Readings

Complete before class. These give you the vocabulary we will use in lecture.

Source Sections Why
Beej-C Chapter 17 (Multifile Projects) sections 1 through 4 The canonical practical walkthrough
Beej-C Chapter 19 (The C Preprocessor) sections 1 through 3 #include, #define, and include guards
King, C Programming: A Modern Approach Chapter 15 (Writing Large Programs) Optional; deeper treatment of file organization
3. Pre-Class Work
Do this first
Plan on 30 to 40 minutes. The reading sets up the vocabulary; the practice exercise primes you for the in-class walkthrough.
Heads up: Quiz 7 today
Quiz 7 (Structs) is given at the start of class today. It covers Lessons 18 and 19. Review the struct material before you come in.

Pre-Class Checklist

1
Read Beej-C Chapter 17 (Multifile Projects), sections 1 through 4
Skim if you have read it before. Notice the words declaration, definition, translation unit, and linker — we will use all four in lecture.
2
Read Beej-C Chapter 19 (The C Preprocessor), sections 1 through 3
The preprocessor is a separate program from the compiler. Understanding what it does to your source before the compiler ever sees it is the prerequisite for understanding include guards.
3
Predict, then verify
Take any earlier lab where your main.c has more than two helper functions. On paper, sketch how you would split that program into a main.c plus a header and a second .c. Which functions go where? Which become static? You will revise your answer in class.
4. Lesson Materials and Overview
Jump to: Slides Overview Four errors Vocabulary Testing Course standard

Slide deck

Lesson 20 slides (PDF)  ·  downloadable copy of the in-class deck. The slides are the spine of the in-class lecture; the header file walkthrough is where you practice the moves hands-on.

What this lesson is really about

All semester you have been writing one big main.c. That works for small programs. Past a few hundred lines, it starts to hurt: search slows down, recompiles get slower, you can't reuse helpers, two cadets cannot work on the same file at once.

The fix is to split. But splitting is not a mechanical chore. Every split is a design decision: which file does this function belong in? What does the header expose, and what stays private? When you make those decisions well, the next person who reads your code (which is often you, six weeks from now) finds what they need immediately.

Today's content is the rules the preprocessor and linker enforce so that splitting actually works, and the design judgment you need to apply on top of those rules.

This is functional decomposition, the same skill you have been practicing since Lesson 6, one level up. At L6 you decided which lines of main should become a helper function. Today you decide which helper functions belong in which file. The judgment is the same; the granularity is bigger.

The four common errors

When you get the rules wrong, the linker (or compiler) tells you. There are basically four patterns to recognize:

  • undefined reference — the linker can't find a function's definition
  • multiple definition — the linker found too many definitions
  • implicit declaration — the compiler reached a call site with no prototype
  • conflicting types — the prototype and the definition disagree

Each of these has a different fix, and learning to map error → cause is the diagnostic skill we are after today. The linker error reference card walks through all four patterns with worked examples. Keep it open while you work the lab.

Vocabulary that will appear in lecture

declaration A promise: "a function (or variable) named X exists somewhere with this signature." Lives in headers.
definition The body. Lives in a .c. There must be exactly one definition per non-static function.
translation unit One .c file plus every header it includes, fully expanded by the preprocessor. The compiler eats one of these at a time.
linker The program that runs after the compiler and stitches your .o files together into one executable. Most multi-file errors come from the linker, not the compiler.
include guard An #ifndef / #define / #endif wrapper around a header that prevents it from being pasted twice into the same translation unit.
static (at file scope) Marks a function as private to its .c. The linker will refuse to let other files call it.

Writing your own tests

Today's lab is the first lesson where you write your own test cases, not just consume the autograder's. Your tests.c file lives alongside main.c and your stats module and builds as its own executable. Each test you write needs a one-line comment naming the edge case it covers and why it matters.

We start the habit here in L20; Lesson 26 (Test Planning and Unit Testing) teaches it formally. The goal today is not perfect coverage; it is the shift from "the autograder tests me" to "I test my code."

DFCS C Programming Standard

Today's lesson is the first contact with five sections of the DFCS C Programming Standard. These rules apply to your code from this lesson forward.

§1.2 Header file structure: comment block, then guard, then includes, then defines, then typedefs, then prototypes.
§4.1 Every header file has an include guard. Macro name is the filename in CAPS with underscores for dots.
§4.2 Include only what you use. Reference a symbol, include the header that declares it directly. No transitive includes.
§2.1 Comment header block on every file, including .h files.
§2.2 Function header blocks in .h files: each prototype gets @brief, @param, @return comments directly above it.

The full standard is in the Resources section on Blackboard. The lab autograder does not mechanically check these sections, but they are enforced for the rest of the course and surface on every quiz and GR from this point.

5. In-Class Work

Today's flow

  1. Quiz 7 (Structs) — 20-minute quiz at the start of class, covering Lessons 18 and 19.
  2. Lecture: declarations vs definitions, what the preprocessor does, the four linker errors.
  3. Header file walkthrough widget (below). Work through it at your own pace.
  4. Linker error diagnostic quiz (below). Six error blocks; identify the cause.
  5. Lab 20 (GitHub Classroom) — start in class, finish at home if needed.
  6. Lesson 20 reflection on Blackboard before the next class.

Header File Walkthrough

A nine-task walkthrough where you organize a small multi-file project. Each command edits the project tree on the right; the errors panel below shows what the linker would say about your current layout. By the end, the errors panel should be clean.

Before you begin

Enter your name. It will appear on the completion screen so you can include it in your screenshot for the Blackboard reflection.

CS210 Lesson 20 · Header File Walkthrough

Organize a small multi-file project. Type commands at the prompt to move declarations, add include guards, and mark helpers static. The errors panel on the right shows what the linker would say about your current layout.
Task 0 of 9
Section 1: Declarations vs definitions
Current task
Loading...
Project: stats/
Build errors
header>
How this works: This is not a Linux shell. It is a teaching tool that simulates how multi-file C projects compile and link. Type a command, and the project tree updates while a small static analyzer recomputes what errors the linker would report. The task card tells you what to do next; the errors panel tells you what to fix.

Linker Error Diagnostic

Six error blocks. For each, identify the most likely cause. Pass at 70% or above. The completion code goes in your Lesson 20 reflection.

Before you begin

Enter your name. It will appear on the score card so you can include it in your screenshot for the Blackboard reflection.

CS210 Lesson 20 · Linker Error Diagnostic

Six error blocks. For each one, identify the most likely cause. Pass at 70% or above; below that, review the linker-error reference card and try again.
How this works: Each card shows a real linker or compiler error block. Pick the cause that best explains it and click Submit. Feedback appears, then click Next. Answers lock once submitted. After all six, you get a score, a completion code, and a per-question recap.

After both widgets

  1. Open the Lab 20 GitHub Classroom link above. Clone the repo to your machine.
  2. Read provided.h and README.md end to end before writing any code.
  3. On paper, sketch your file split. What goes in main.c, what goes in your own .c, and which header declares what?
  4. Write the code. Test as you go — don't write everything and hope.
  5. Run make and confirm zero warnings, then run both binaries before you push.
6. After Class
  • Finish Lab 20 if you did not complete it in class. Submit through GitHub Classroom and Gradescope before Lesson 21.
  • Complete the Lesson 20 reflection on Blackboard. You need the completion codes from both widgets.
  • Read Beej-C Chapter 19 (The C Preprocessor) sections 4 through 6 (conditional compilation, macros with arguments) for Lesson 21.
  • Heads up: Lesson 21 extends today's project to read flight data from a file. The file structure you set up today is what L21 builds on.
  • Upcoming graded events: PEX1 is due Lesson 21, and Quiz 8 (File I/O) is at Lesson 22. Block 3 is dense — plan your week accordingly.
Need help? Schedule EI with your instructor. Bring the exact linker or compiler error you are seeing and the contents of the file the error points to. The linker error reference card covers the four common patterns; the Resources section on Blackboard has the full DFCS C Programming Standard and the Git troubleshooting reference.