Intermediate · The preprocessor, multi-file programs and make · topic 38 of 60 · 25 min
Splitting a program into files
Explanation
Why split?
A single 20,000-line file is hard to read, slow to recompile, and impossible for a team to edit without conflicts. Splitting by responsibility (tax.c, invoice.c, storage.c) lets each part be understood, tested and rebuilt on its own.
A header and its source file
/* tax.h: the interface */
#ifndef TAX_H
#define TAX_H
double gst_amount(double price, int rate_percent);
extern int default_gst_rate; /* declared here, defined in tax.c */
#endif/* tax.c: the implementation */
#include "tax.h"
int default_gst_rate = 18; /* the one definition */
static double round2(double x) { /* private to tax.c (static) */
return (long)(x * 100 + 0.5) / 100.0;
}
double gst_amount(double price, int rate_percent) {
return round2(price * rate_percent / 100.0);
}/* main.c: a user of the module */
#include <stdio.h>
#include "tax.h" /* "" searches the project folder first; <> the system folders */
int main(void) {
printf("GST: %.2f\n", gst_amount(1499.0, default_gst_rate)); /* GST: 269.82 */
return 0;
}gcc -std=c17 -Wall -c tax.c # → tax.o
gcc -std=c17 -Wall -c main.c # → main.o
gcc tax.o main.o -o billing # link
# or in one step: gcc -std=c17 -Wall tax.c main.c -o billingWhat goes where
| In the header (.h) | In the source (.c) |
|---|---|
| Include guard | Function bodies |
| Type definitions (struct, typedef, enum) others need | Global variable definitions (int x = 0;) |
| Function prototypes | static helper functions and variables |
| extern declarations of shared globals | #include of its own header first |
| Macros and static inline functions others need |
Reading linker errors
/usr/bin/ld: main.o: in function 'main':
main.c:(.text+0x1a): undefined reference to 'gst_amount'
collect2: error: ld returned 1 exit status/usr/bin/ld: tax.o:(.data+0x0): multiple definition of 'default_gst_rate'; main.o:(.data+0x0): first defined hereNeed help?
Stuck on a word or an idea? Search this course, or every course, and jump straight to the explanation or a worked question.
Try:
Watch the lesson
Splitting a program into files · 1/6
In this lesson you will split a C program into several files.
Prefer a video by a teacher? Find free videos on “c multiple source files header files extern linker errors undefined reference” on YouTube ↗
In real life: Organising a clinic billing program
A clinic's billing tool grew from one file into modules: patient.c/h (patient records), tax.c/h (GST on services), invoice.c/h (building invoices) and main.c (menus). When the GST rules changed, only tax.c was edited and recompiled, and the rest of the program relinked in seconds.
billing/
├── main.c
├── patient.h patient.c
├── tax.h tax.c
└── invoice.h invoice.c (invoice.c includes patient.h and tax.h)Practice (0/3 done)
You compile with gcc main.c -o app and get "undefined reference to `gst_amount'". The function is in tax.c. What is the fix?
config.h contains int max_users = 100; and is included by three .c files. What happens at link time?
Split a small program into money.h/money.c (a Money type in paise with add, multiply-by-quantity and format functions), cart.h/cart.c (adding items to a cart and computing the total using money.h) and main.c. Use include guards, keep helpers static, compile each file with -c, and link. Then deliberately cause and fix an "undefined reference" and a "multiple definition" error.
Quick quiz
Read more (free)
Related help
Before this, learn
This topic builds on these. If something here feels new, open them first.
Related topics
- Building with makeThe preprocessor, multi-file programs and make · same module
- The preprocessor and macrosThe preprocessor, multi-file programs and make · same module
- Functions: declare, define, call and returnC++ Programming (modern C++ and DSA) · Decisions, loops and functions
- Compiling with gccGetting started with C
- What C++ is and how compiling worksC++ Programming (modern C++ and DSA) · First steps: compiling, output, variables and input
- Prototypes and the prototype chainJavaScript Programming (language in depth) · Scope, this, prototypes and classes
Questions people ask about this
Open a question to see the answer and why. The first ones are this topic's own quiz, so try the quiz above before you peek.
What does gcc -c file.c produce?
Answer: An object file (file.o) that is not yet linked
Compile only, no linking.
What does extern int count; in a header mean?
Answer: count is defined in some .c file; this just declares it
A declaration without storage.
What is the difference between #include "x.h" and #include <x.h>?
Answer: "" searches the project's folders first; <> searches the system include folders
Use "" for your own headers.
Which belongs in a header?
Answer: A function prototype
Prototypes and types.
Which include style is used for your own header file?Related
Answer: #include "myfile.h"
Quotes search your project folder first; angle brackets are for standard and system headers.
What does extern int count; mean?Related
Answer: count is defined somewhere else (another file)
A declaration, not a definition.
What is a prototype for?Related
Answer: To declare the function's signature before it is used
The compiler can then check calls.
From Functions
Which stage expands #include and #define?Related
Pass the quiz (60% or more) or mark this topic as done when you are ready.
Your progress is saved on this device only.
Next steps
- 2 more topics in “The preprocessor, multi-file programs and make” before its exam: Building with make, Libraries: static and shared.
- Module 8 exam: Preprocessor, multi-file programs and make · 12 questions · 25 min, without help. 5 topics of this module still to finish first.
- Then the next module, Bits, undefined behaviour and safety. 60 topics left in the course before the final exam.