Table of Contents
The GNU Compiler Collection (GCC) is a widely used compiler for various programming languages, including C. Compiling a C program with GCC is a fundamental skill for any developer working in the C language. In this article, we will discuss how to compile C programs with GCC, providing examples and explanations for the various flags available, and their corresponding outputs.
It will also help to know about the compilation process of a C program.
Getting Started with GCC
First, ensure that you have GCC installed on your system. You can check its presence by running the following command in the terminal or on CMD for windows:
gcc --version
If GCC is not installed, follow the official installation guidelines for your operating system.
Compiling a Basic C Program with GCC
To compile a C program using GCC, follow these steps:
- Write a simple C program and save it with the “.c” extension. For this example, we will use a basic “Hello, World!” program named “hello.c”:
#include <stdio.h> int main() { printf("Hello, World!\n"); return 0; }
- Open a terminal and navigate to the directory where the “hello.c” file is located.
- Compile the program using the following command:
gcc -o hello hello.c
This command tells GCC to compile the “hello.c” source file and create an executable output file named “hello”. The “-o” flag is used to specify the output file name.
- To run the compiled program, enter the following command:
./hello
You should see the output “Hello, World!” printed on the terminal.
Using GCC Flags to Modify Compilation
GCC provides several flags that can be used to modify the compilation process. Here are some common flags and their functions:
-Wall
This flag enables all common warning messages during compilation. It helps identify potential issues in your code.
Example:
gcc -Wall -o hello hello.c
-g
This flag adds debugging information to the executable file, allowing you to use a debugger (such as GDB) to analyze your program.
Example:
gcc -g -o hello hello.c
-O
This flag is followed by a number (0-3) to specify the optimization level. Higher levels (e.g., -O2
or -O3
) apply more aggressive optimizations, which can result in faster and smaller executables, but may take longer to compile.
Example:
gcc -O2 -o hello hello.c
-std
This flag is followed by a specific C standard (e.g., c99
or c11
) to specify the language standard you want to use during compilation.
Example:
gcc -std=c99 -o hello hello.c
-I
This flag is followed by a directory path to specify additional include directories. It is useful when your program relies on external header files.
Example:
gcc -I/path/to/headers -o hello hello.c
-L
and -l
These flags are used to specify library directories and libraries, respectively. Use -L
to add a directory to the library search path and -l
to link against a specific library.
Example:
gcc -o hello hello.c -L/path/to/libs -lmylib
In this example, the “mylib” library located in the “/path/to/libs” directory will be linked to the program.
In this continuation, we will explore additional examples that demonstrate how to use more advanced GCC features.
Example 1: Compiling Multiple Source Files with GCC
Suppose you have a larger project with multiple source files. You can compile them all into a single executable by specifying each source file in the command:
- Create two C source files, “main.c” and “helper.c”, along with a header file “helper.h”:
main.c:
#include <stdio.h> #include "helper.h" int main() { printf("The sum of 3 and 5 is: %d\n", add(3, 5)); return 0; }
helper.h:
int add(int a, int b);
helper.c:
#include "helper.h" int add(int a, int b) { return a + b; }
- Compile the project using the following command:
gcc -o my_program main.c helper.c
This command tells GCC to compile both “main.c” and “helper.c” source files and create an executable output file named “my_program”.
- Run the compiled program:
./my_program
You should see the output “The sum of 3 and 5 is: 8” printed on the terminal.
Example 2: Using Static Libraries in GCC
- First, create a static library from the “helper.c” source file:
gcc -c helper.c -o helper.o ar rcs libhelper.a helper.o
The first command compiles “helper.c” into an object file “helper.o” without linking. The second command creates a static library named “libhelper.a” from the “helper.o” object file.
- Compile the “main.c” source file and link it with the static library:
gcc -o my_program main.c -L. -lhelper
This command tells GCC to compile the “main.c” source file and link it with the “libhelper.a” library located in the current directory (indicated by -L.
). The -lhelper
flag specifies the library name without the “lib” prefix and the file extension.
- Run the compiled program:
./my_program
You should see the same output as before: “The sum of 3 and 5 is: 8”.
Example 3: Using Shared Libraries in GCC
- Create a shared library from the “helper.c” source file:
gcc -c -fPIC helper.c -o helper.o gcc -shared -o libhelper.so helper.o
The first command compiles “helper.c” into an object file “helper.o” with position-independent code (PIC) suitable for shared libraries. The second command creates a shared library named “libhelper.so” from the “helper.o” object file.
- Compile the “main.c” source file and link it with the shared library:
gcc -o my_program main.c -L. -lhelper
The command is the same as in the static library example, but this time, it will link against the shared library “libhelper.so” instead of the static library “libhelper.a”.
- Before running the program, ensure that the shared library can be found by the dynamic linker:
export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:.
- Run the compiled program:
./my_program
You should see the same output as before: “The sum of 3 and 5 is: 8”.
Example 4: Compiling with Warnings as Errors in GCC
In some cases, you might want to treat all warnings as errors, which can help you maintain strict coding standards and prevent potential issues. To achieve this, use the -Werror
flag:
- Create a C source file named “warning_example.c” with an unused variable:
#include <stdio.h> int main() { int unused_variable; printf("This program has an unused variable.\n"); return 0; }
- Compile the program using the following command:
gcc -Wall -Werror -o warning_example warning_example.c
This command tells GCC to enable all common warning messages with -Wall
and treat them as errors with -Werror
.
The compilation will fail, and you will see a message similar to this:
warning_example.c: In function 'main': warning_example.c:5:9: error: unused variable 'unused_variable' [-Werror=unused-variable] int unused_variable; ^~~~~~~~~~~~~~ cc1: all warnings being treated as errors
- To successfully compile the program, remove or use the
unused_variable
in the code, and then compile it again.
Example 5: Generating Assembly Code with GCC
Sometimes, you may want to inspect the generated assembly code to understand the low-level operations your program performs. To generate assembly code, use the -S
flag:
- Create a simple C program (or use an existing one) and save it with the “.c” extension. For this example, we will use the basic “Hello, World!” program named “hello.c” from the previous sections.
- Generate the assembly code using the following command:
gcc -S hello.c -o hello.s
This command tells GCC to generate the assembly code for the “hello.c” source file and create an output file named “hello.s”. The -S
flag is used to stop the compilation process after the compilation stage, and the -o
flag specifies the output file name.
- Open the generated “hello.s” file in a text editor to inspect the generated assembly code. The assembly code will be specific to your system’s architecture and may vary between systems.
In this article, we covered various examples demonstrating how to use advanced features of GCC, including compiling multiple source files, using static and shared libraries, treating warnings as errors, and generating assembly code. Understanding these concepts will help you become a more proficient C programmer and enable you to use GCC effectively in your projects.
Hi, I’m Vivek, a Senior Embedded Innovation Specialist. I have been working on Embedded Systems and IoT for the past 11 years. I love to share my knowledge and train those who are interested. Nerdyelectronics.com was started out of this interest. You can read my full profile in this link.