The Preprocessor
Before a single line of your C code is actually compiled into machine instructions, it passes through a separate program called the preprocessor. The preprocessor performs a purely textual transformation of your source file: it deletes comments, pastes in the contents of included files, expands macros, and strips out or keeps blocks of code depending on conditional directives. Only after all of that text-substitution work is done does the real compiler ever see the result.
A Separate Pass, Before Real Compilation
Every directive that starts with a # (like #include, #define, or #if) is an instruction to the preprocessor, not to the C compiler itself. The overall pipeline for a single source file looks like this:
.cfile with#directives goes inPreprocessor: strips comments, pastes in included files, expands macros, resolves conditional blocks
The result is pure C source with no
#directives left (mostly) — this is called a translation unitThe real compiler parses and compiles that translation unit into object code
Viewing the Preprocessed Output
You do not have to take this on faith — GCC and Clang let you stop the pipeline right after the preprocessing stage and dump the result with the -E flag.
gcc -E hello.c -o hello.i # hello.i now contains the fully expanded, macro-substituted, # comment-free C source that the real compiler would have seen.
#define GREETING "Hello, preprocessor!"
#include <stdio.h>
int main(void)
{
printf("%s\n", GREETING);
return 0;
}Run gcc -E on the snippet above and you will see the entire contents of stdio.h pasted in verbatim near the top of the output, followed by your main function with GREETING replaced literally by the string "Hello, preprocessor!". Nothing magical happens — it is a mechanical find-and-replace.
The Main Directive Families
Family | Directives | Purpose |
|---|---|---|
Macros |
| Define text substitutions — simple constants or function-like expansions |
File inclusion |
| Paste the contents of another file (usually a header) in place |
Conditional compilation |
| Include or exclude blocks of source text based on compile-time conditions |
Other |
| Compiler-specific hints, forced compile errors, line-number bookkeeping |
The next few pages dig into each directive family in depth, starting with the most commonly used one: macros.