thecodex.expert · The Codex Family of Knowledge
C

Multi-file Projects

Each .c file is compiled completely independently, with zero visibility into any other file’s internals — a separate linking step afterward is what stitches the resulting object files into one program.

C17 / C23 Compile separately, link together Last verified:
Canonical Definition

Compilation happens per-file: gcc -c file.c produces file.o, an object file containing compiled machine code plus a table of symbols it defines and symbols it needs from elsewhere. The linker then resolves those cross-references, combining every .o file into one executable — this is why a function must be DECLARED (via a header, typically) in any file that calls it, even though its actual DEFINITION lives in just one .c file elsewhere. static at file scope restricts a function or global variable's visibility to just its own file (internal linkage); without static, it's visible to every other file in the program by default (external linkage) — the opposite default from most modern languages.

A real 3-file project: header, implementation, and main

main.c never sees mymath.c's actual code — only the declarations in mymath.h. This separation is exactly what lets mymath.c be recompiled without touching main.c at all, when only its implementation changes.

Cmymath.h
#ifndef MYMATH_H
#define MYMATH_H

int add(int a, int b);

#endif
Cmymath.c
#include "mymath.h"

int add(int a, int b) {
    return a + b;
}
Cmain.c
#include <stdio.h>
#include "mymath.h"

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

Compiling and linking separately

Each -c compiles ONE file to an object file without linking; the final command links both .o files together into one executable — exactly the sequence a Makefile automates.

Cterminal
$ gcc -c mymath.c   // produces mymath.o
$ gcc -c main.c       // produces main.o
$ gcc -o myapp main.o mymath.o   // LINKS the two object files together
$ ./myapp

static: restricting a name to its own file

Without static, this internal() function would be visible (and callable) from any other file in the program by default — C's default linkage is the opposite of most modern languages, where privacy is opt-in rather than the baseline.

Chelper.c
static void internalHelper(void) {   // static: only visible within THIS file
    // implementation detail, not part of this file's public API
}

void publicFunction(void) {             // no static: visible to other files (via a header)
    internalHelper();
}

Sources

1
ISO/IEC 9899 (C Standard), "Storage-class specifiers" and "Linkage of identifiers," cppreference.com/w/c/language/storage_duration.