Compiling a C Program: Behind the Scenes

We hit "Build", and seconds later, an executable appears. But what actually happens in that black box? The transformation from human-readable C code to machine-executable binary involves four distinct stages.

main.c
#include <stdio.h>

#define MAX 10

int main() {
    printf("Hello, Silicon! count: %d\n", MAX);
    return 0;
}

1. Preprocessing

The preprocessor (cpp) handles directives starting with #.

Command: gcc -E main.c -o main.i

2. Compilation

The compiler (cc1) translates the preprocessed code (.i) into Assembly Language (.s). This is where syntax checking and optimization happen.

Command: gcc -S main.i -o main.s

3. Assembly

The assembler (as) translates assembly instructions into machine code (object code). The output is a relocatable object file (.o)—it's binary code, but not yet executable.

Command: gcc -c main.s -o main.o

4. Linking

The linker (ld) combines your object file with standard libraries (like the implementation of printf in libc). It resolves symbol references and arranges the final memory layout to produce the actual executable.

Final Command: gcc main.o -o main

Takeaway: Understanding this pipeline helps debug linker errors and optimize code for embedded systems where every byte counts.