Appearance
[中文版本](/posts/c教程/zh-CN/01-入门/006-Compiling, Linking, and Executing)
When you press Enter to compile your C program, a lot happens behind the scenes. Your source code goes through several stages before it becomes a runnable executable. Understanding these steps is essential, it turns compilation errors from mysteries into simple, fixable clues.
Tiny Code
Let’s start with a familiar program:
#include <stdio.h>
int main(void) {
printf("Learning the C build process!\n");
return 0;
}Now compile and run it step by step:
# Step 1: Compile to object file
gcc -c hello.c -o hello.o
# Step 2: Link object file into executable
gcc hello.o -o hello
# Step 3: Run the program
./helloOutput:
Learning the C build process!The Four Stages of Building a C Program
Preprocessing The preprocessor handles all lines starting with#. It expands macros, includes headers, and prepares code for compilation. Command to inspect:
gcc -E hello.c | lessCompilation The compiler translates the preprocessed code into assembly language, and then into object code. Each source file (likehello.c) becomes an object file (hello.o). Command:
gcc -c hello.cLinking The linker combines all object files and libraries into one final executable. For example,printf comes from the C standard library (libc), so the linker connects your code to it. Command:
gcc hello.o -o helloExecution Once linked, your binary (hello) is loaded by the operating system and executed by the CPU. Command:
./helloWhy It Matters
C gives you control over every stage of this process. Most modern languages hide compilation or linking, but in C, these steps are transparent and configurable. When something goes wrong, a missing function, an undefined symbol, or a broken include, you’ll know exactly which stage to look at.
Mastering the build process also opens the door to deeper skills:
- Creating reusable libraries (
.aor.sofiles) - Understanding Makefiles and build automation
- Debugging with symbols and optimized builds
- Writing portable programs that compile cleanly anywhere
Every system programmer eventually learns to think like a compiler, and this is where that thinking begins.
Try It Yourself
Experiment with separate compilation:
Create two files:
main.c
#include <stdio.h>
void greet(void);
int main(void) {
greet();
return 0;
}greet.c
#include <stdio.h>
void greet(void) {
printf("Hello from another file!\n");
}Then compile and link:
gcc -c main.c
gcc -c greet.c
gcc main.o greet.o -o greetprog
./greetprogTry breaking it: Delete thevoid greet(void); line inmain.c and recompile, see how the compiler warns you about an implicit declaration.
Observe the stages: Add flags like-Wall -O2 -v to see detailed messages from the compiler and linker.
Once you understand compilation and linking, you’ve unlocked one of the most powerful parts of C, the ability to control exactly how your software is built, combined, and executed.
