C Academy · Lesson

Multi-File Projects

Headers and translation units.

Lesson 2 of 413 steps

Multi-File Projects is a free C Academy lesson on CoddyKit. This is lesson 2 of 4. You can read the complete lesson below for free — then practise it hands-on in the browser with a built-in code editor and a 24/7 AI tutor. It is part of the C Academy learning path, and your progress syncs across the web and the CoddyKit app. The C Academy course includes 4 lessons in total.

Why Split Files

Real programs do not live in one .c file. Splitting code into multiple files:

  • Groups related functions together
  • Lets the compiler rebuild only what changed
  • Makes code reusable across projects
  • Lets a team work without constant conflicts

Understanding how the pieces link is essential.

Translation Units

Each .c file, after the preprocessor expands its #includes, becomes a translation unit.

The compiler turns each translation unit into an object file (.o) independently. It does not know about other files at this stage.

Declaration vs Definition

A declaration tells the compiler a function exists and its signature. A definition provides the actual body.

Other files only need the declaration to call a function. The definition lives in exactly one place.

int add(int a, int b);          /* declaration: a promise */

int add(int a, int b) {         /* definition: the body */
    return a + b;
}

The Header File

Declarations go in a header (.h). Any file that wants to use the function includes the header.

The header is the public interface; the matching .c file is the private implementation.

/* math_utils.h */
#ifndef MATH_UTILS_H
#define MATH_UTILS_H

int add(int a, int b);
int mul(int a, int b);

#endif

The Implementation File

The .c file includes its own header and defines the functions.

Including your own header lets the compiler verify the definitions match the declarations.

/* math_utils.c */
#include "math_utils.h"

int add(int a, int b) { return a + b; }
int mul(int a, int b) { return a * b; }

Using The Module

Another file includes the header and calls the functions. It never needs to see the bodies.

The compiler trusts the declarations; the linker will connect the calls to the real definitions later.

/* main.c */
#include <stdio.h>
#include "math_utils.h"

int main(void) {
    printf("%d\n", add(2, 3));
    return 0;
}

Compiling And Linking

Two phases. First compile each file to an object file with -c. Then link the objects into one executable.

The linker resolves each call to add by finding its definition in math_utils.o.

gcc -c main.c          # -> main.o
gcc -c math_utils.c    # -> math_utils.o
gcc main.o math_utils.o -o app

Quotes vs Angle Brackets

Include syntax controls the search path:

  • #include "math_utils.h" searches your project directory first
  • #include <stdio.h> searches only system include paths

Use quotes for your own headers, angle brackets for the standard library.

The extern Keyword

To share a global variable across files, define it once in a .c file and declare it with extern in the header.

extern says 'this variable exists somewhere else', avoiding duplicate definitions.

/* in config.h */
extern int g_verbose;   /* declaration */

/* in config.c */
int g_verbose = 0;      /* the single definition */

The static Keyword

At file scope, static makes a function or variable private to its translation unit.

A static helper cannot be linked from other files, preventing name clashes and hiding implementation details. It is the C way to mark something internal.

/* visible only inside this .c file */
static int helper(int x) {
    return x * 2;
}

The One Definition Rule

A non-static function or global may be defined exactly once across the whole program. Declare it in many files, but define it in one.

Two definitions of add produce a linker error like multiple definition of 'add'. This is why bodies stay out of headers.

Quick Check

Reason about what belongs in a header.

Recap

You can now structure a multi-file project:

  • Each .c is a translation unit compiled to a .o independently
  • Headers hold declarations; one .c holds each definition
  • The linker resolves calls across object files
  • extern shares globals; static keeps file-local symbols private

Next: automating the build with Makefiles.

Free to start

Learn C with an AI tutor — free

Write and run real code in your browser, get instant help from a 24/7 AI tutor, and pick up where you left off on the web or in the app.

Courses
39
Lessons
144

Frequently Asked Questions

Is the “Multi-File Projects” lesson free?

Yes — the full text of “Multi-File Projects” is free to read here on the web. To practise it interactively (a built-in code editor and a 24/7 AI tutor) and unlock the rest of the C Academy course, upgrade to CoddyKit PRO. The C Academy course includes 4 lessons in total.

What will I learn in “Multi-File Projects”?

Headers and translation units. You practise C Academy with hands-on code you run directly in the browser, and a 24/7 AI tutor answers your questions as you work through the lesson.

Do I need any experience to start C Academy?

No prior experience is required. C Academy on CoddyKit is structured for beginners through advanced learners, so you can start here or from the beginning and move at your own pace. This is lesson 2 of 4.

How long does the “Multi-File Projects” lesson take?

Most CoddyKit lessons take about 5–10 minutes. Each one is bite-sized and interactive, so you make steady progress and pick up exactly where you left off across the web and the app.

Can I write and run code in this C Academy lesson?

Yes. Every C Academy lesson includes a built-in code editor, so you write and run real code right in your browser and get instant AI feedback — no local setup required.

All lessons in this course

  1. Conditional Compilation
  2. Multi-File Projects
  3. Makefiles
  4. Static and Shared Libraries
← Back to C Academy