Compilation Process in C

Oduwole Dare
2 min readJun 1, 2023

It’s sometimes great to look under the hood and know what happens when you compile a C file. By exploring this process, developers gain insights into how their programs are transformed into functional software.

Image credit: Markus Spiske

It is interesting to know that your C files are compiled from human-readable source code to machine-executable binaries in four stages Preprocessing, Compiling, Assembling, and Linking.

  1. Preprocessor: This converts the source file into an intermediate file. At this stage, the preprocessor directives (lines starting with the # symbol) manipulate the source code by including header files, defining macros, and removing comments from the code. The extension of the intermediate file is “.i”
                                *--------------*
Hello.c ==| gcc -E hello.c |==> | Preprocessor | -> Hello.i
*--------------*

2. Compiler: This converts the intermediate file into an assembly code, which is a low-level representation of the program. Here is where most instructions are added to the file, analysis of the syntax and semantics of the code, error checking, and generation of optimized assembly code. If any errors or warnings are encountered during this phase, the compiler halts and provides diagnostic messages to assist in debugging of the code.

                                *----------*
Hello.i ==| gcc -S hello.c |==> | compiler | -> Hello.s // open in an editor or cat
*----------*

3. Assembler: This converts the assembler program into an object file, which can be binary or hexadecimal codes. These codes are executable but may include unresolved references to external symbols and libraries. This linking issue is then handled by the last phase — Linking.

                                        *-----------*
Hello.s ==| gcc hello.c -o hello.o |==> | Assembler | -> Hello.o
*-----------*

4. Linker: This merges all the object files (library files) and combines them with external libraries to create an executable file (binary file). The linker performs several crucial tasks, including symbol resolution, relocation, and merging of object files. It also eliminates unused code and resolves dependencies between different modules.

                             *--------*
Hello.c ==| gcc hello.c |==> | linker | -> Hello
*--------*

Conclusion

Understanding the compilation process is fundamental for any C programmer. It allows developers to comprehend the transformations their code undergoes before becoming a functional program. From preprocessing to assembly code generation, object file creation, and finally, the linking process, each step contributes to the final executable file.
By grasping the compilation process, programmers gain insights into potential issues that may arise during development and learn techniques to optimize their code.

Other Articles

42 Minitalk Explained
42 Push Swap Explained With Psuedocodes

--

--