← thecodex.expert · The Codex Family of Knowledge
C

Header Files

#include isn’t a real import statement — it’s the preprocessor literally copy-pasting a file’s text into yours, before the compiler even looks at either one.

C17 / C23 #include = textual paste Last verified:
Canonical Definition

A header file (.h) declares function prototypes, struct/type definitions, and macros meant to be shared across multiple .c source files, without containing their actual implementations. #include works via the C preprocessor, which runs before real compilation and literally replaces the #include line with the entire contents of the named file — there's no module system, namespace, or dedicated import mechanism underneath; it's pure textual substitution.

Angle brackets vs quotes

<stdio.h> searches the compiler's standard system include paths first; "myheader.h" searches the current directory (relative to the including file) first, then falls back to the system paths — the distinction matters for finding your own project's headers vs the standard library's.

Cmain.c
#include <stdio.h>     // system header: standard library
#include "mymath.h"       // your own project header, in the local directory

Declaring in a header, defining in a .c file

The header declares add()'s signature (plus a small Point type it works with) so any file including it knows how to call it correctly; the actual implementation lives in exactly one .c file, compiled separately and linked together afterward. Note the two declarations aren't equally fragile: a plain function prototype like int add(int a, int b); can legally appear more than once in a translation unit — repeating it verbatim isn't an error. A type definition like the Point struct below is different: defining the same tag/typedef twice is a genuine "conflicting types" error, which is exactly the double-inclusion risk the next section covers.

Cmymath.h
typedef struct {
    int x;
    int y;
} Point;

int add(int a, int b);   // declaration only — no body
Cmymath.c
#include "mymath.h"

int add(int a, int b) {   // the actual implementation, in ONE place
    return a + b;
}

Include guards: preventing double-inclusion

If the same header gets #included twice in one translation unit (a common situation when several headers each include a shared one), the preprocessor pastes its contents twice. For the bare add() prototype alone that's harmless — a repeated, identical declaration compiles fine (verified: zero warnings even with -Wall -Wextra -Wpedantic). But Point's definition would genuinely be pasted twice too, and that is a real "conflicting types" compile error (verified directly: gcc rejects a struct typedef defined twice with that exact message) — headers commonly mix declarations that tolerate repetition with type/macro definitions that don't, so the safe default is to guard the whole file. An include guard — or the equivalent, more concise #pragma once — makes the second inclusion a no-op.

Cmymath.h
#ifndef MYMATH_H   // classic include guard: "if MYMATH_H isn't defined yet"
#define MYMATH_H

typedef struct {
    int x;
    int y;
} Point;

int add(int a, int b);

#endif

// or, more concisely (widely supported, though not part of the official standard):
// #pragma once

Sources

1
ISO/IEC 9899 (C Standard), "Source file inclusion," cppreference.com/w/c/preprocessor/include.