Compilation in C is the process of converting source code into an executable program that a computer can run. The source code passes through several stages, including preprocessing, compilation, assembly, and linking, before the final executable is generated.
- Each stage transforms the program into a format required by the next stage.
- Tools such as GCC (GNU Compiler Collection) automate these stages to generate executable programs.
How Does the Compilation Process Work
A C program passes through four main stages before an executable file is created:

- Preprocessing: Processes header files, macros, and conditional compilation directives.
- Compilation: Converts preprocessed C code into assembly code.
- Assembly: Converts assembly code into machine-code object files.
- Linking: Combines object files and resolves references to external functions and variables to produce an executable.
Steps to Compile and Run a C Program
Let's create a simple C program and compile it using GCC on Linux.
Step 1: Create a C Source File
Create a file named filename.c using a text editor. On Linux, you can use the following command:
vi filename.c
Add the following C program to the file:
#include <stdio.h>
int main() {
printf("Hello World\n");
return 0;
}
Step 2: Compile the Program Using GCC
Open the terminal in the directory containing filename.c and execute:
gcc -Wall filename.c -o filename
Here:
- gcc: Invokes the GCC compiler driver.
- -Wall: Enables a commonly used set of compiler warnings.
- filename.c: Specifies the source file to compile.
- -o filename: Specifies the executable file name.
Note: On Linux, GCC normally generates an executable named a.out if the -o option is not provided.
Step 3: Execute the Program
Run the generated executable using:
./filename
The program will be executed, and the output will be shown in the terminal.

The program executes and displays the message in the terminal.
Stages of the C Compilation Process
GCC normally performs preprocessing, compilation, assembly, and linking automatically. However, we can examine the intermediate files generated during these stages.
Use the following command:
gcc -Wall -save-temps filename.c -o filename
The -save-temps option preserves intermediate files so we can inspect the compilation process.
The generated files typically include:
File | Description |
|---|---|
filename.c | Original C source code |
filename.i | Preprocessed C source code |
filename.s | Assembly code |
filename.o | Object file containing machine code |
filename | Final executable program |

Below is the explanation for all the intermediate processes and files:
1. Preprocessing
Preprocessing is the first stage of the compilation process. The preprocessor handles directives that begin with # before the compiler processes the C code.
The main tasks performed during preprocessing are:
- Removes comments from the source code.
- Expands macros defined using #define.
- Processes header files included using #include.
- Handles conditional compilation directives such as #ifdef and #ifndef.
Example: Consider the following C code:
#include <stdio.h>
#define VALUE 10
int main(){
printf("%d\n", VALUE);
return 0;
}
During preprocessing, VALUE is replaced with 10, and the contents of the included header file are processed. To generate the preprocessed output separately, use:
gcc -E filename.c -o filename.i
You can inspect the file using:
less filename.i
The filename.i file contains preprocessed C code that is passed to the compilation stage.
2. Compilation
In this stage, the compiler processes the preprocessed source code, performs language analysis and optimization as applicable, and generates assembly code. The compiler checks the program for errors such as invalid syntax and incompatible types.
To generate the assembly file, use:
gcc -S filename.i -o filename.s

The assembly code represents low-level instructions that can be translated into machine code by an assembler.
3. Assembly
The assembler converts the assembly code into machine instructions and produces an object file. To generate the object file, use:
gcc -c filename.s -o filename.o
The generated filename.o file contains machine code along with information needed for linking.
At this stage:
- Assembly instructions are converted into machine code.
- Symbol and relocation information is stored in the object file.
- References to external functions, such as printf(), may remain unresolved until linking.
The object file is not normally a complete executable program.

4. Linking
Linking is the final stage of the compilation process. The linker combines object files with the required libraries and resolves references to external functions and variables.
For example, when a program uses printf(), the linker processes the reference to the function provided by the C standard library.
To link the object file, use:
gcc filename.o -o filename
The resulting filename file is an executable program.
The linking process generally performs the following tasks:
- Combines object files into an executable.
- Resolves references to functions and variables across files.
- Incorporates required runtime startup code and library dependencies.
Types of Linking in C
Linking is generally classified into two types:
1. Static Linking:
In static linking, the required code from static libraries is incorporated into the executable during the linking process.
- Produces an executable containing the required statically linked library code.
- Generally increases executable size compared with using shared libraries.
2. Dynamic Linking:
In dynamic linking, the executable refers to shared libraries whose code is loaded and linked as needed at runtime.
- Allows multiple programs to use shared library code.
- Usually reduces executable size because shared library code is not copied into the executable.
Compilation Vs Linking
Basis | Compilation | Linking |
|---|---|---|
Purpose | Translates source code into lower-level instructions | Combines object files and resolves references |
Input | Preprocessed source code | Object files and libraries |
Output | Assembly code in the GCC pipeline | Executable file or shared library |
Main Task | Checks and translates program code | Resolves symbols and combines compiled components |
Tool | Compiler | Linker |