C Notes
Learn everything about GCC compiler including installation, compilation stages, important flags, optimization levels, and debugging options. Complete GCC tutorial for C programming beginners.
GCC (GNU Compiler Collection) is the most widely used open-source compiler for C and C++ programming. Originally created by Richard Stallman in 1987 as part of the GNU Project, GCC has become the default compiler on Linux systems and is available on virtually every platform. Whether you're a student writing your first program or a systems programmer building operating systems, understanding GCC is essential.
What is GCC?
GCC stands for GNU Compiler Collection. While it originally stood for "GNU C Compiler," it has grown to support multiple programming languages including C, C++, Objective-C, Fortran, Ada, and Go.
When people say "GCC" in the context of C programming, they typically mean the gcc command-line tool that compiles C source code into executable programs.
Why GCC is Important
- Free and Open Source — Available at no cost under the GPL license
- Cross-Platform — Works on Linux, macOS, Windows (via MinGW/MSYS2), and many other systems
- Standards Compliant — Supports C89, C99, C11, C17, and C23 standards
- Industry Standard — Used to compile the Linux kernel, Git, Python interpreter, and thousands of other projects
- Powerful Optimization — Includes advanced optimization capabilities for producing fast executables
Basic GCC Usage
The simplest way to compile a C program with GCC:
gcc program.cThis produces an executable named a.out (on Linux/macOS) or a.exe (on Windows). To specify a custom output name:
gcc program.c -o programNow you can run it with ./program on Linux/macOS or program.exe on Windows.
The Four Stages of Compilation
GCC doesn't convert your source code to an executable in a single step. It goes through four distinct stages, and understanding these stages will make you a better programmer and debugger.
Stage 1: Preprocessing (-E)
The preprocessor handles all directives that start with #:
- Expands
#includedirectives (inserts header file contents) - Replaces
#definemacros with their values - Evaluates
#ifdef/#ifndefconditional compilation - Removes comments
gcc -E program.c -o program.iThe output .i file contains the expanded source code. For a simple Hello World program, this file can be thousands of lines long because the entire stdio.h header (and its dependencies) gets included.
Stage 2: Compilation (-S)
The compiler takes the preprocessed source code and converts it into assembly language specific to your target architecture (x86, ARM, etc.).
gcc -S program.c -o program.sYou can open the .s file to see the assembly instructions. This is useful for understanding how the CPU will actually execute your code.
Stage 3: Assembly (-c)
The assembler converts the assembly language into machine code (binary object file). This file contains the actual instructions that the CPU understands, but it's not yet a complete executable.
gcc -c program.c -o program.oThe .o file (object file) contains machine code but may have unresolved references to external functions (like printf from the C library).
Stage 4: Linking
The linker takes one or more object files and combines them with library code (like the C standard library) to produce the final executable.
gcc program.o -o programDuring linking, all external function calls are resolved — the linker finds where printf actually lives in the C library and connects your code to it.
Essential GCC Flags and Options
Compilation Control Flags
| Flag | Purpose | Example |
|---|---|---|
-o filename | Specify output file name | gcc prog.c -o prog |
-c | Compile only, don't link | gcc -c prog.c |
-S | Generate assembly only | gcc -S prog.c |
-E | Preprocess only | gcc -E prog.c |
-v | Verbose output (show all steps) | gcc -v prog.c |
Warning Flags
Warnings help you catch potential bugs and write cleaner code. Always compile with warnings enabled!
| Flag | Purpose |
|---|---|
-Wall | Enable all common warnings |
-Wextra | Enable extra warnings beyond -Wall |
-Werror | Treat all warnings as errors |
-Wpedantic | Warn about non-standard code |
-Wshadow | Warn when a variable shadows another |
-Wunused | Warn about unused variables/functions |
Recommended command for development:
gcc -Wall -Wextra -Werror program.c -o programThis forces you to write clean, warning-free code — a great habit to build early.
C Standard Selection
You can tell GCC which version of the C standard to use:
# Compile using C99 standard
gcc -std=c99 program.c -o program
# Compile using C11 standard
gcc -std=c11 program.c -o program
# Compile using C17 standard (latest stable)
gcc -std=c17 program.c -o program
# Use GNU extensions with C11
gcc -std=gnu11 program.c -o programOptimization Levels
GCC can optimize your code to run faster or use less memory:
| Level | Description | Use Case |
|---|---|---|
-O0 | No optimization (default) | Debugging — fastest compile time |
-O1 | Basic optimizations | Moderate improvement, reasonable compile time |
-O2 | Standard optimizations | Good balance of speed and compile time |
-O3 | Aggressive optimizations | Maximum performance, may increase binary size |
-Os | Optimize for size | Embedded systems, small binaries |
-Og | Optimize for debugging | Better than -O0 but debugger-friendly |
# For development and debugging
gcc -O0 -g program.c -o program
# For release builds
gcc -O2 program.c -o program
# For maximum performance
gcc -O3 program.c -o programDebugging Flags
| Flag | Purpose |
|---|---|
-g | Include debugging information (for GDB) |
-g3 | Maximum debugging info including macro definitions |
-ggdb | Produce GDB-specific debugging info |
-fsanitize=address | Enable AddressSanitizer (detect memory errors) |
-fsanitize=undefined | Enable UndefinedBehaviorSanitizer |
# Compile for debugging with GDB
gcc -g -O0 program.c -o program
# Compile with memory error detection
gcc -g -fsanitize=address program.c -o programCompiling Multiple Files
Real projects usually have multiple source files. GCC handles this easily:
# Compile multiple files at once
gcc main.c utils.c math_ops.c -o myapp
# Or compile separately and link
gcc -c main.c -o main.o
gcc -c utils.c -o utils.o
gcc -c math_ops.c -o math_ops.o
gcc main.o utils.o math_ops.o -o myappThe second approach is preferred for large projects because you only need to recompile files that changed — this is the basis of how make and build systems work.
Linking with Libraries
Standard Math Library
The math library (libm) needs to be explicitly linked:
gcc program.c -o program -lmThe -l flag tells the linker to search for a library. -lm means "link with libm" (the math library).
Custom Libraries
# Link with a shared library
gcc program.c -o program -L/path/to/lib -lmylibrary
# Link with a static library
gcc program.c -o program /path/to/libmylibrary.a| Flag | Purpose |
|---|---|
-l | Link with a library |
-L | Add library search path |
-I | Add include (header) search path |
-static | Force static linking |
Checking GCC Version
gcc --versiongcc (Ubuntu 13.2.0-23ubuntu4) 13.2.0 Copyright (C) 2023 Free Software Foundation, Inc. This is free software; see the source for copying conditions.
To see detailed configuration:
gcc -vUseful GCC Commands for Students
# Basic compilation with warnings
gcc -Wall -Wextra program.c -o program
# See all preprocessing output
gcc -E program.c | less
# Generate assembly to study
gcc -S -O2 program.c -o program.s
# Check what GCC defines automatically
gcc -dM -E - < /dev/null
# Compile for 32-bit on a 64-bit system
gcc -m32 program.c -o program
# Show all included headers
gcc -H program.c -o programGCC vs Other Compilers
| Feature | GCC | Clang | MSVC |
|---|---|---|---|
| Platform | All major OS | All major OS | Windows only |
| License | GPL | Apache/MIT | Proprietary |
| Error Messages | Good | Excellent | Good |
| C Standard Support | Excellent | Excellent | Good (improving) |
| Optimization | Excellent | Excellent | Very Good |
| Build Speed | Good | Very Good | Good |
Common GCC Errors and Solutions
Undefined Reference
undefined reference to 'sqrt'
Solution: Link with the math library: gcc prog.c -o prog -lm
No Such File or Directory
fatal error: myheader.h: No such file or directory
Solution: Use -I to specify the include path: gcc -I./includes prog.c -o prog
Implicit Declaration Warning
warning: implicit declaration of function 'myFunc'
Solution: Include the proper header file or add a function prototype before use.
Interview Questions
Q1: What are the four stages of GCC compilation?
The four stages are: (1) Preprocessing — handles #include, #define, removes comments; (2) Compilation — converts preprocessed code to assembly language; (3) Assembly — converts assembly to machine code (object files); (4) Linking — combines object files with libraries to create the final executable. You can stop at any stage using flags -E, -S, -c respectively.
Q2: What is the difference between -O2 and -O3 optimization levels?
-O2 enables standard optimizations that improve performance without significantly increasing binary size or compilation time. -O3 enables all -O2 optimizations plus additional aggressive ones like function inlining, loop vectorization, and loop unrolling. -O3 may produce faster code but can increase binary size and occasionally cause issues with floating-point precision or code that relies on undefined behavior.
Q3: Why should you compile with -Wall -Wextra flags?
These flags enable comprehensive warning messages that help catch potential bugs, uninitialized variables, unused parameters, type mismatches, and other issues at compile time rather than runtime. -Wall enables common warnings while -Wextra adds additional checks. Using these flags promotes writing cleaner, more portable, and more reliable code.
Q4: What is the difference between static and dynamic linking?
Static linking (-static) copies all library code directly into the executable, making it self-contained but larger. Dynamic linking (default) references shared libraries (.so on Linux, .dll on Windows) at runtime, producing smaller executables but requiring the libraries to be present on the system. Static linking is portable; dynamic linking saves memory when multiple programs use the same library.
Q5: What does the -g flag do in GCC?
The -g flag tells GCC to include debugging information (symbol tables, line numbers, variable names) in the compiled binary. This information is used by debuggers like GDB to map machine instructions back to source code lines, allowing you to set breakpoints, inspect variables, and step through code during debugging sessions. It increases binary size but has no effect on runtime performance.
Summary
- GCC (GNU Compiler Collection) is the industry-standard open-source compiler for C programming
- Compilation involves four stages: preprocessing, compilation, assembly, and linking
- Always use
-Wall -Wextraduring development to catch potential bugs early - Use
-gflag when you need to debug with GDB - Optimization levels range from
-O0(none) to-O3(aggressive) - Use
-std=c11or-std=c17to specify which C standard to follow - Link external libraries with
-lflag (e.g.,-lmfor math) - Multiple source files can be compiled separately and linked together
- GCC is available on all major platforms and is essential knowledge for any C programmer
Mastering GCC flags and options will make you significantly more productive as a C programmer. Start with the basics (-Wall -o), and gradually incorporate more flags as your programs grow in complexity.
Exam Focus
Revise definitions, diagrams, examples, and short-answer points for GCC Compiler - Complete Guide to GNU C Compiler.
Interview Use
Prepare one clear explanation, one practical example, and one common mistake for this C Programming topic.
Search Terms
c-programming, c programming, programming, setup, gcc, compiler, gcc compiler - complete guide to gnu c compiler
Related C Programming Topics