Compilation stages — preprocessing, compilation, assembly, linking

WHY does this pipeline exist?
Stage 1 — Preprocessing
WHAT it does:
#include <stdio.h>→ physically pastes the entire contents of that header file.#define PI 3.14→ replaces everyPItoken with3.14.#ifdef / #ifndef / #endif→ keeps or deletes blocks of code conditionally.- Strips comments.
HOW to see it:
gcc -E hello.c -o hello.i # -E = stop after preprocessingStage 2 — Compilation
WHAT happens inside:
- Lexing → break text into tokens.
- Parsing → build an Abstract Syntax Tree (AST).
- Semantic analysis → type checks (this is where most of your errors come from!).
- Optimization → e.g. constant folding
2*3→6. - Code generation → emit assembly for the target CPU (x86, ARM…).
HOW to see it:
gcc -S hello.i -o hello.s # -S = stop after compilationStage 3 — Assembly
WHY not runnable yet? Because it may call functions (like printf) that live in other files. Their addresses are still unknown placeholders.
HOW to see it:
gcc -c hello.s -o hello.o # -c = compile+assemble, stop before linkingStage 4 — Linking
WHAT it resolves:
- Your
hello.osays "I needprintf". The linker findsprintfinside the C standard library (libc) and patches the address in.
Two kinds:
- Static linking → library code is copied into the executable (bigger file, self-contained).
- Dynamic linking → only a reference is stored; the actual
.so/.dllis loaded at runtime (smaller file, shared).
HOW:
gcc hello.o -o hello # links, produces executableCommon Mistakes (Steel-manned)
Forecast-then-Verify
80/20 — The vital few
Recall Feynman: explain to a 12-year-old
Imagine you wrote a recipe in English. First, a helper copies in all the sub-recipes you referenced and fixes up shorthand notes (preprocess). Then a translator rewrites it into the chef's special cooking-shorthand (compile). A second person turns that shorthand into exact robot-arm button presses (assemble) — but the recipe still says "use sauce from the other kitchen". Finally, the linker runs around collecting all the sauces from other kitchens and glues everything into ONE finished cookbook the robot can run start-to-finish.
Connections
- Build Systems & Toolchain
- Static vs Dynamic Linking
- Object files and symbol tables
- Make and incremental builds
- ABI and calling conventions
- Preprocessor macros and include guards
Flashcards
What are the 4 compilation stages in order?
Which gcc flag stops after preprocessing?
-E (produces .i)Which gcc flag stops after compilation (emits assembly)?
-S (produces .s)Which gcc flag compiles+assembles but does not link?
-c (produces .o)What does the preprocessor actually do to #include?
What is a translation unit?
# directives left), the actual input to the compiler.Why is SQ(x) ((x)*(x)) parenthesized?
SQ(3+1).What does the assembler produce and why isn't it runnable?
.o) with machine code, but it has unresolved symbols and placeholder addresses.What is the linker's main job?
At which stage does undefined reference to 'x' occur?
Static vs dynamic linking?
Where do type-checking errors occur?
What lives in an object file's symbol table?
File extension chain for a C program?
.c → .i → .s → .o → executableConcept Map
Hinglish (regional understanding)
Intuition Hinglish mein samjho
Dekho, jab tum gcc hello.c -o hello chalाते ho, lagta hai ek hi step hai — par andar 4 stages chalte hain, ek factory line ki tarah. Pehla stage hai preprocessing: yeh sirf text ka kaam karta hai. Jitne bhi # waale lines hain (#include, #define), unhe handle karta hai — header file ka pura content paste kar deta hai, aur macros ko replace kar deta hai. Yeh math nahi samajhta, sirf text copy-paste karta hai, isliye macros mein parentheses zaroori hain.
Dusra stage compilation hai — yahan asli C code ko assembly language mein convert karta hai. Yahi par type-checking aur syntax errors pakde jaate hain, aur optimization hoti hai. Output .s file hota hai jo CPU-specific hota hai (x86, ARM). Teesra assembly stage assembly ko raw machine code (.o object file) banata hai — par yeh abhi run nahi ho sakta, kyunki printf jaise functions ke address abhi unknown hain.
Aakhri stage linking hai. Yeh sab object files aur libraries ko jod kar ek executable banata hai, aur saare "I need printf" jaise symbols ko resolve karta hai. Agar koi function use hua par kahin defined nahi mila, to undefined reference error aata hai — yaad rakho yeh link-time error hai, compile error nahi! Tumhara syntax sahi tha, bas definition ya library missing thi.
Exam aur debugging dono ke liye yeh samajhna critical hai: agar error expected ';' jaisa hai to compile stage, agar undefined reference hai to link stage, aur agar #include file nahi mili to preprocess stage. Isse tum turant pata laga loge ki problem kahan hai — yahi 80/20 fayda hai.