The Process Of Compiling C Programs Explained

C is a low-level programming language meaning that by itself it cannot be read by the computer. It needs to be compiled with a compiler (gcc for example) in order to be “translated” into code that your computer will understand (i.e. binary). In this article, we will explain the process of compiling C programs.
The compiler components
The compiler is not a single module compiler, it has four big modules and can be simply described as it follows:

- Preprocessor: a program that modifies data to conform with the input requirements of the compiler.
- Compiler: generates an assembly code from the preprocessor input
- Assembler: convert the assembly code into a computer-readable code (i.e. binary)
- Linker: used with the assembler to provide links to the libraries needed for an executable program
Let’s look at these steps in-depth
For the sake of this exercise, let’s consider the following C program hello.c
:
#include <stdio.h>
/**
* main - Entry point
*
* Return: Always 0 (Success)
*/
int main(void)
{
printf("Hello World\n");
return (0);
}
If we were to run this program the expected output should simply be:
Hello World
But before this happens we need to compile the program so it can be executed.
For that, we will be using the shell command gcc
. Obviously, the command gcc hello.c
allows you to firectly create a a.out
executable file for your C program. Like so:
Command: gcc hello.c && ./a.out
Output: Hello World
But in order to understand the process we will brake it down into the 4 modules to check out how the compiler works.
Preprocessor
The gcc
command allows us to process the file without compiling, assembling and linking it.
Let’s preprocess it and save its output on a file named hello_p
and print the first 10 lines:
Command:
gcc -E hello.c > hello_p
and then… head hello_p
Output:
# 1 "hello.c"# 1 "<built-in>"# 1 "<command-line>"# 1 "/usr/include/stdc-predef.h" 1 3 4# 1 "<command-line>" 2# 1 "hello.c"# 1 "/usr/include/stdio.h" 1 3 4# 27 "/usr/include/stdio.h" 3 4# 1 "/usr/include/features.h" 1 3 4# 374 "/usr/include/features.h" 3 4
Compiler
Now let’s compile it only and see its output in the file hello.o
:
Command:
gcc -c hello.c > hello.o
and less hello.o
Output:
^?ELF^B^A^A^@^@^@^@^@^@^@^@^@^A^@>^@^A^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@0^A^@^@^@^@^@^@^@^@^@^@@^@^@^@^@^@@^@^M^@^@UH<89><E5><BF>^@^@^@^@<E8>^@^@^@^@<B8>^@^@^@^@]<C3>Hello World^@^@GCC: (Ubuntu 4.8.4-2ubuntu1~14.04.4) 4.8.4^@^@^@^@^T^@^@^@^@^@^@^@^AzR^@^Ax^P^AESC^L^G^H<90>^A^@^@^\^@^@^@^\^@^@^@^@^@^@^@^U^@^@^@^@A^N^P<86>^BC^M^FP^L^G^H^@^@^@^@.symtab^@.strtab^@.shstrtab^@.rela.text^@.data^@.bss^@.rodata^@.comment^@.note.GNU-stack^@.rela.eh_frame^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@ ^@^@^@^A^@^@^@^F^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@@^@^@^@^@^@^@^@^U^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^A^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@ESC^@^@^@^D^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@<90>^E^@^@^@^@^@^@0^@^@^@^@^@^@^@^K^@^@^@^A^@^@^@^H^@^@^@^@^@^@^@^X^@^@^@^@^@^@^@&^@^@^@^A^@^@^@^C^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@U^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^A^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@,^@^@^@^H^@^@^@^C^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@U^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^A^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@1^@^@^@^A^@^@^@^B^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@U^@^@^@^@^@^@^@^L^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^A^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@9^@^@^@^A^@^@^@0^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@a^@^@^@^@^@^@^@,^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^A^@^@^@^@^@^@^@^A^@^@^@^@^@^@^@B^@^@^@^A^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@<8D>^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^A^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@W^@^@^@^A^@^@^@^B^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@<90>^@^@^@^@^@^@^@8^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^H^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@R^@^@^@^D^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@<C0>^E^@^@^@^@^@^@^X^@^@^@^@^@^@^@^K^@^@^@^H^@^@^@^H^@^@^@^@^@^@^@^X^@^@^@^@^@^@^@^Q^@^@^@^C^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@<C8>^@^@^@^@^@^@^@a^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^A^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^A^@^@^@^B^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@p^D^@^@^@^@^@^@^H^A^@^@^@^@^@^@^L^@^@^@ ^@^@^@^H^@^@^@^@^@^@^@^X^@^@^@^@^@^@^@ ^@^@^@^C^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@x^E^@^@^@^@^@^@^S^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^A^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^A^@^@^@^D^@<F1><FF>^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^C^@^A^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^C^@^C^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^C^@^D^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^C^@^E^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^C^@^G^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^C^@^H^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^C^@^F^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@ ^@^@^@^R^@^A^@^@^@^@^@^@^@^@^@^U^@^@^@^@^@^@^@^N^@^@^@^P^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@hello.c^@main^@puts^@^@^@^@^@^@^E^@^@^@^@^@^@^
Assembler
Now let’s assemble it only and see its output in the file hello.s
:
Command:
gcc -S hello.c > hello.s
and less hello.s
Output:
.file "hello.c".section .rodata.LC0:.string "Hello World".text.globl main.type main, @functionmain:.LFB0:.cfi_startprocpushq %rbp.cfi_def_cfa_offset 16.cfi_offset 6, -16movq %rsp, %rbp.cfi_def_cfa_register 6movl $.LC0, %edicall putsmovl $0, %eaxpopq %rbp.cfi_def_cfa 7, 8ret.cfi_endproc.LFE0:.size main, .-main.ident "GCC: (Ubuntu 4.8.4-2ubuntu1~14.04.4) 4.8.4".section .note.GNU-stack,"",@progbits
Linker
This time we’ll checkout what a fully compiled file looks like.
Now we can directly insert the following:
Command: gcc hello.c
and then less a.out
Output:
^?ELF^B^A^A^@^@^@^@^@^@^@^@^@^B^@>^@^A^@^@^@@^D@^@^@^@^@^@@^@^@^@^@^@^@^@x^Q^@^@^@^@^@^@^@^@^@^@@^@8^@ ^@@^@^^^@ESC^@^F^@^@^@^E^@^@^@@^@^@^@^@^@^@^@@^@@^@^@^@^@^@@^@@^@^@^@^@^@<F8>^A^@^@^@^@^@^@<F8>^A^@^@^@^@^@^@^H^@^@^@^@^@^@^@^C^@^@^@^D^@^@^@8^B^@^@^@^@^@^@8^B@^@^@^@^@^@8^B@^@^@^@^@^@^\^@^@^@^@^@^@^@^\^@^@^@^@^@^@^@^A^@^@^@^@^@^@^@^A^@^@^@^E^@^@^@^@^@^@^@^@^@^@^@^@^@@^@^@^@^@^@^@^@@^@^@^@^@^@^L^G^@^@^@^@^@^@^L^G^@^@^@^@^@^@^@^@ ^@^@^@^@^@^A^@^@^@^F^@^@^@^P^N^@^@^@^@^@^@^P^N`^@^@^@^@^@^P^N`^@^@^@^@^@0^B^@^@^@^@^@^@8^B^@^@^@^@^@^@^@^@ ^@^@^@^@^@^B^@^@^@^F^@^@^@(^N^@^@^@^@^@^@(^N`^@^@^@^@^@(^N`^@^@^@^@^@<D0>^A^@^@^@^@^@^@<D0>^A^@^@^@^@^@^@^H^@^@^@^@^@^@^@^D^@^@^@^D^@^@^@T^B^@^@^@^@^@^@T^B@^@^@^@^@^@T^B@^@^@^@^@^@D^@^@^@^@^@^@^@D^@^@^@^@^@^@^@^D^@^@^@^@^@^@^@P<E5>td^D^@^@^@<E0>^E^@^@^@^@^@^@<E0>^E@^@^@^@^@^@<E0>^E@^@^@^@^@^@4^@^@^@^@^@^@^@4^@^@^@^@^@^@^@^D^@^@^@^@^@^@^@Q<E5>td^F^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^P^@^@^@^@^@^@^@R<E5>td^D^@^@^@^P^N^@^@^@^@^@^@^P^N`^@^@^@^@^@^P^N`^@^@^@^@^@<F0>^A^@^@^@^@^@^@<F0>^A^@^@^@^@^@^@^A^@^@^@^@^@^@^@/lib64/ld-linux-x86-64.so.2^@^D^@^@^@^P^@^@^@^A^@^@^@GNU^@^@^@^@^@^B^@^@^@^F^@^@^@^X^@^@^@^D^@^@^@^T^@^@^@^C^@^@^@GNU^@<D1><98>J<BA>^]L^Q<C0>)a=<DB>F<84><A9>^W<]p<E7>^A^@^@^@^A^@^@^@^A^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^K^@^@^@^R^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^P^@^@^@^R^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@"^@^@^@ ^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@libc.so.6^@puts^@__libc_start_main^@__gmon_start__^@GLIBC_2.2.5^@^@^@^@^B^@^B^@^@^@^@^@^A^@^A^@^A^@^@^@^P^@^@^@^@^@^@^@u^Zi ^@^@^B^@1^@^@^@^@^@^@^@<F8>^O`^@^@^@^@^@^F^@^@^@^C^@^@^@^@^@^@^@^@^@^@^@^X^P`^@^@^@^@^@^G^@^@^@^A^@^@^@^@^@^@^@^@^@^@^@^P`^@^@^@^@^@^G^@^@^@^B^@^@^@^@^@^@^@^@^@^@^@(^P`^@^@^@^@^@^G^@^@^@^C^@^@^@^@^@^@^@^@^@^@^@H<83><EC>^HH<8B>^E^M^L ^@H<85><C0>t^E<E8>;^@^@^@H<83><C4>^H<C3>^@^@^@^@^@^@<FF>5^B^L ^@<FF>%^D^L ^@^O^_@^@<FF>%^B^L ^@h^@^@^@^@<E9><E0><FF><FF><FF><FF>%<FA>^K ^@h^A^@^@^@<E9><D0><FF><FF><FF><FF>%<F2>^K ^@h^B^@^@^@<E9><C0><FF><FF><FF>1<ED>I<89><D1>^H<89><E2>H<83><E4><F0>PTI<C7><C0><C0>^E@^@H<C7><C1>P^E@^@H<C7><C7>-^E@^@<E8><B7><FF><FF><FF><F4>f^O^_D^@^@<B8>G^P`^@UH-@^P`^@H<83><F8>^NH<89><E5>w^B]<C3><B8>^@^@^@^@H<85><C0>t<F4>]<BF>@^P`^@<FF><E0>^O^_<80>^@^@^@^@<B8>@^P`^@UH-@^P`^@H<C1><F8>^CH<89><E5>H<89><C2>H<C1><EA>?H^A<D0>H<D1><F8>u^B]<C3><BA>^@^@^@^@H<85><D2>t<F4>]H<89><C6><BF>@^P`^@<FF><E2>^O^_<80>^@^@^@^@<80>=Y^K ^@^@u^QUH<89><E5><E8>~<FF><FF><FF>]<C6>^EF^K ^@^A<F3><C3>^O^_@^@H<83>=^X ^@^@t^^<B8>^@^@^@^@H<85><C0>t^TU<BF> ^N`^@H<89><E5><FF><D0>]<E9>{<FF><FF><FF>^O^_^@<E9>s<FF><FF><FF>UH<89><E5><BF><D4>^E@^@<E8><D5><FE><FF><FF><B8>^@^@^@^@]<C3>f.^O^_<84>^@^@^@^@^@^O^_@^@AWA<89><FF>AVI<89><F6>AUI<89><D5>ATLa.out