Compilation of C programs

Author
By Darío Rivera
Posted On in Lenguaje C

In a previous post we saw how to create our first program in C, the classic Hello World!. However, we saw a very simple way to compile and execute that program. Today we will see a little more in depth how to compile C language programs.

Compilation process

First of all, let's see a little about the process by which a program becomes a C executable.

compilation diagram

It all starts with editing the program using an editor in which we save the file with the extension .c. This file is the entry point for the compiler which converts it into an object file with extension .o or .obj in some compilers. Finally, the linker or linker editor transforms it into an executable file for the machine. Generally, if the extension is not specified, it will be an .out file.

Additionally, this file can be taken by the debugger to debug when we obtain unexpected results or when we want to verify that everything is running well by running the program step by step.

The compilation process is usually a bit more complex than the one shown above. When the compiler is invoked, the preprocessor is responsible (before compiling) for processing the compiler directives. That is, all lines that start with the # character. Once this is done, the file is passed to the compiler to perform the compilation process.

preprocessor diagram

Compiler installation

Most Linux systems have C and C++ compilers. On GNU/Linux Debian-based systems, simply run the following command to install the GCC compiler.

sudo apt-get install gcc

If you are using Ubuntu you can follow this tutorial that gives you everything you need to get started with C.

- Getting started with C in Ubuntu 22.04 (Jammy Jellyfish)

Simple compilation

Remember that to compile a program, it is enough to execute the compilation command, in our case gcc, and specify the name of the file.

gcc program.c

This will create by default the output file called a.out. To specify the output file name, we can use the -o option.

gcc program.c -o program

Where program.c is the C code file and program is the compiled file that will be generated. Even when our program has references to other header files, we only need to compile our main file. Example:

main.c

#include <stdio.h>
#include "variables.c"

int main()
{
    printf("PI is %.4f\n", pi);
    return 0;
}

variables.c

float pi = 3.1516;

This program includes the file variables.c. What the preprocessor does in these cases is to include the content of the file in our main file to process it as if it were one. Understanding this is very important because if we have really large programs it can be a headache to compile the entire program this way.

Compilation of multiple files

Compiling multiple files occurs when we add header files that generally come from external libraries. Let's see the following example:

main.c

#include <stdio.h>
#include "mylib.h"

int main()
{
    printf("PI is %.4f\n", pi);
    return 0;
}

mylib.h

extern float pi;

mylib.c

float pi = 3.1516;

To compile this program we must run the following command referencing our two files with extension .c.

gcc main.c mylib.c

Note that extern has been used to reference variables created in another file. This modifier has the advantage of not creating a new space in memory and allowing us to modularize our program. This same example could be compiled per steps, something that would be very useful in large applications where if we make a change in a file we would have to compile the entire application again.

gcc -c mylib.c
gcc -c main.c
gcc main.o mylib.o

When executing gcc -c file.c an object file is generated. This is so because the -c parameter prevents the compiler from linking the files, so it generates the object files for us to do the linking ourselves.

Files with the extension .o are object files that the compiler has processed and are passed to the linker to produce an executable program.

If we had a very large number of dependencies and made a change in dependency X, the next step to compile would be the same.

gcc -c X.c
gcc -c main.c
gcc main.o X.o A.o B.o C.o

In where A.o, B.o, C.o are other generated dependencies.

Execution

To run the program, just run it as follows:

./output

Acerca de Darío Rivera

Author

Application Architect at Elentra Corp . Quality developer and passionate learner with 10+ years of experience in web technologies. Creator of EasyHttp , an standard way to consume HTTP Clients.

LinkedIn Twitter Instagram

Sólo aquellos que han alcanzado el éxito saben que siempre estuvo a un paso del momento en que pensaron renunciar.