What happens when you type gcc main.c?
Compiling is the process of transforming code in one programming language to another. If we’re programming in almost any language such as C, the computer initially won’t understand what we’ve written, so we need to use a compiler to translate what we wrote into machine code and to create an executable program. There are four steps to building an executable program: pre-processing, compiling, assembly, and linking.
I’ll demonstrate the changes going on in each step with snapshots. Let’s start with a program ‘main.c’ that prints “Hello World!”
In pre-processing, the compiler substitutes preprocessor directives (lines like #include and #define) with their values. The <stdio.h> directive is a header file which contains code declaring the library resources. This header is replaced with function declarations for standard file input and output. The preprocessor copies and pastes these functions in place of the header. To run the code through the preprocessor, we can use the compiler gcc and use the option -E, creating a file ‘main.i’. Below is a snippet of code in ‘main.i’:
The next step is compiling, or transforming the code from a higher level to a lower level language. With our “Hello World!” program, this step transforms the code from C to assembly. To get to this step using gcc, use the option -S, creating ‘main.s.’
In assembly, the assembly code is translated into machine code (object file main.o). While the compilation is complete, the object files still need to be combined into an executable program. This step is called linking.
The linker combines object files. In the case of main.o, stdio.h is linked to main.o to produce an executable file (by default named ‘a.out’). Note: while stdio.h is always linked because it is in the library libc, some header files may not be recognized. For math.h, the flag lm has to be added to the compiler.