Neural Architecture Hub
C & C++

GCC

GCC command-line cheatsheet from first compilation to debugging, linking, optimization, and production builds.

GCC Cheatsheet

GCC is the GNU Compiler Collection. For ordinary projects:

CommandUse It For
gccCompile and link C programs
g++Compile and link C++ programs; automatically links the C++ standard library
cppRun only the C/C++ preprocessor
gcovRead coverage data generated by GCC

The basic pattern is:

gcc [options] input.c -o output
g++ [options] input.cpp -o output

Examples on this page use Unix-style executable names (./app). On Windows with MinGW, run the output as app.exe.


1. Beginner: Compile and Run

First C Program

// hello.c
#include <stdio.h>

int main(void) {
    puts("Hello, GCC!");
    return 0;
}
gcc hello.c -o hello       # Compile and link
./hello                    # Run on Linux/macOS

First C++ Program

// hello.cpp
#include <iostream>

int main() {
    std::cout << "Hello, GCC!\n";
}
g++ hello.cpp -o hello     # Use g++ for C++ linking
./hello

Essential Commands

CommandMeaning
gcc main.cBuild C program as a.out (a.exe on some Windows setups)
gcc main.c -o appName the output executable app
gcc -std=c17 main.c -o appCompile using the C17 language standard
g++ -std=c++20 main.cpp -o appCompile C++20 source
gcc --versionPrint GCC version
gcc -v main.c -o appShow commands and paths used while building
gcc -std=c17 -Wall -Wextra -Wpedantic -g main.c -o app
FlagPurpose
-std=c17Select a defined C standard
-WallEnable many common warnings
-WextraEnable additional useful warnings
-WpedanticWarn about non-standard language extensions
-gInclude debug information for a debugger

Warnings are not failures by default. Fix warnings instead of ignoring them.


2. How Compilation Works

GCC usually performs four stages:

source.c -> preprocessed source -> assembly -> object file -> executable
             preprocessing          compile       assemble      link
StageGCC OptionTypical OutputWhat Happens
Preprocess-E.iExpands #include, #define, and conditional compilation
Compile-S.sTranslates C/C++ into assembly
Assemble-c.oProduces machine-code object file without linking
Linkdefault final stepexecutable/libraryResolves functions and combines object files/libraries
gcc -E hello.c -o hello.i   # Stop after preprocessing
gcc -S hello.c -o hello.s   # Stop after generating assembly
gcc -c hello.c -o hello.o   # Stop after object file
gcc hello.o -o hello        # Link object into executable

Keep Intermediate Files

gcc -save-temps hello.c -o hello

This is useful when learning, investigating macros, or inspecting generated assembly.


3. Common Option Reference

Input and Output

OptionExamplePurpose
-o file-o calculatorSet output filename
-cgcc -c util.cCompile only; do not link
-Egcc -E config.cPreprocess only
-Sgcc -S math.cGenerate assembly
-x languagegcc -x c input.txtTreat input as a particular language
-pipegcc -pipe main.cUse pipes between compilation stages where supported

Standards

LanguageCommon Selection
C90-std=c90
C11-std=c11
C17-std=c17
GNU C17 extensions-std=gnu17
C++17-std=c++17
C++20-std=c++20
GNU C++20 extensions-std=gnu++20

-std=c17 is stricter and more portable; -std=gnu17 also allows GNU extensions commonly used on Linux.

Macros and Include Paths

OptionExamplePurpose
-DNAME-DDEBUGDefine macro with value 1
-DNAME=value-DPORT=8080Define macro with a value
-UNAME-UDEBUGUndefine a macro
-I dir-IincludeAdd header search directory
-iquote dir-iquote src/includeSearch directory for quoted includes only
-isystem dir-isystem vendor/includeAdd system header directory with reduced warning noise
#ifdef DEBUG
fprintf(stderr, "x = %d\n", x);
#endif
gcc -DDEBUG -Iinclude src/main.c -o app

4. Warnings and Diagnostics

Sensible Warning Sets

# Everyday C development
gcc -std=c17 -Wall -Wextra -Wpedantic -Wconversion -Wshadow main.c -o app

# Everyday C++ development
g++ -std=c++20 -Wall -Wextra -Wpedantic -Wconversion -Wshadow main.cpp -o app

# Continuous integration: reject newly introduced warnings
gcc -std=c17 -Wall -Wextra -Wpedantic -Werror main.c -o app
OptionCatches or Controls
-WallFrequently useful warnings such as unused values and suspicious constructs
-WextraAdditional parameter, comparison, and initializer warnings
-WpedanticExtensions beyond the selected standard
-WconversionImplicit conversions that may alter a value
-Wsign-conversionSigned/unsigned conversions
-WshadowDeclarations hiding earlier names
-Wformat=2Stricter printf/scanf format checking
-WundefUnknown identifiers used in preprocessor #if expressions
-WerrorTreat warnings as errors
-Wno-error=nameKeep one warning non-fatal under -Werror

-Wall does not mean every possible warning. Strong warning flags can be noisy on legacy or third-party code, so introduce them deliberately.

More Readable Errors

gcc -fdiagnostics-color=always -fdiagnostics-show-option main.c -o app
gcc -fmax-errors=5 main.c -o app
OptionPurpose
-fdiagnostics-color=alwaysColorize compiler output when the terminal supports it
-fdiagnostics-show-optionShow the warning flag associated with a message
-fmax-errors=nStop after n errors

5. Debug Builds

Debug Build Recipe

gcc -std=c17 -Wall -Wextra -Wpedantic -g -O0 main.c -o app
gdb ./app
OptionPurpose
-gGenerate debugger information
-ggdbGenerate debugging information tailored for GDB
-O0Turn off most optimization for straightforward stepping
-OgOptimize while preserving a useful debugging experience
-fno-omit-frame-pointerMake stack traces/profiling easier on many targets

For most active debugging, this is a useful balance:

gcc -std=c17 -Wall -Wextra -g3 -Og -fno-omit-frame-pointer main.c -o app

Useful Debug Tools

gdb ./app                         # Interactive debugger
gcc -E main.c | less              # Inspect expanded macros/includes
gcc -S -fverbose-asm main.c       # Assembly with compiler comments
gcc -H -c main.c                  # Print included header hierarchy

6. Finding Memory and Undefined-Behavior Bugs

Sanitizers add runtime checks. Use them in testing and debugging builds, not as your usual optimized production binary.

Address and Undefined Behavior Sanitizers

gcc -std=c17 -Wall -Wextra -g -Og \
  -fsanitize=address,undefined -fno-omit-frame-pointer \
  main.c -o app

./app
SanitizerOptionDetects Examples
AddressSanitizer-fsanitize=addressOut-of-bounds access, use-after-free, some leaks
UndefinedBehaviorSanitizer-fsanitize=undefinedInvalid shifts, signed overflow, misaligned access
LeakSanitizer-fsanitize=leakHeap allocations not released
ThreadSanitizer-fsanitize=threadData races in multithreaded programs

Do not combine -fsanitize=thread with -fsanitize=address in the same executable. Sanitizer availability and behavior depend on the target platform and GCC installation.

Static Analysis

gcc -std=c17 -Wall -Wextra -fanalyzer -c main.c

-fanalyzer explores paths through code to report issues such as double-free, null dereference, and some resource leaks. It can be slower and may need judgment when reviewing results.


7. Multiple Source Files

Small Project Layout

project/
  include/math_utils.h
  src/main.c
  src/math_utils.c
# One command: compile and link everything
gcc -std=c17 -Wall -Wextra -Iinclude \
  src/main.c src/math_utils.c -o app

# Separate compilation: rebuild only changed files
gcc -std=c17 -Wall -Wextra -Iinclude -c src/main.c -o main.o
gcc -std=c17 -Wall -Wextra -Iinclude -c src/math_utils.c -o math_utils.o
gcc main.o math_utils.o -o app

Header Dependency Generation

When a header changes, its dependent source files must be rebuilt. GCC can generate dependency rules for make:

gcc -std=c17 -Wall -Wextra -MMD -MP -Iinclude -c src/main.c -o main.o
OptionPurpose
-MMDWrite a .d dependency file for user headers
-MPAdd dummy targets so removed headers do not break old dependency files
-MF fileChoose dependency output file
-MT targetChoose dependency rule target name

8. Linking Libraries

gcc main.c -lm -o app       # Link libm for functions such as sqrt() on Unix-like systems
gcc main.c -pthread -o app  # Compile/link POSIX threads where supported
OptionPurpose
-lNAMELink a library named like libNAME.so or libNAME.a
-LdirAdd a library search directory
-pthreadEnable and link thread support on compatible systems
-Wl,optionPass comma-separated option(s) to the linker

For traditional linkers, put libraries after object files that need them:

gcc main.o geometry.o -Llib -lshape -lm -o app

Create a Static Library

gcc -std=c17 -O2 -Iinclude -c src/math_utils.c -o math_utils.o
ar rcs libmathutils.a math_utils.o
gcc main.o -L. -lmathutils -o app

Static libraries are copied into the final executable as required during linking.

Create a Shared Library on Linux

gcc -std=c17 -O2 -fPIC -Iinclude -c src/math_utils.c -o math_utils.o
gcc -shared math_utils.o -o libmathutils.so
gcc main.o -L. -lmathutils -Wl,-rpath,'$ORIGIN' -o app
OptionPurpose
-fPICGenerate position-independent code commonly required for shared libraries
-sharedProduce a shared library rather than an executable
-Wl,-rpath,...Embed a runtime library search path; use with care when packaging

Shared-library commands and filename conventions differ on Windows and macOS.


9. Optimization and Release Builds

Optimization Levels

OptionTypical UseNotes
-O0Initial debuggingFast compile; easiest source-level stepping
-OgDebugging with reasonable performanceKeeps many debugging expectations intact
-O1Light optimizationSmaller optimization cost
-O2General release buildStrong default for many applications
-O3Benchmark-driven performance workCan increase size; measure results
-OsOptimize for sizeUseful for constrained binaries
-OfastAggressive performanceMay relax language/IEEE math guarantees

Release Build Recipe

gcc -std=c17 -O2 -DNDEBUG -Wall -Wextra main.c -o app

-DNDEBUG disables the standard assert() macro. Use it only when removing runtime assertions is appropriate for the release.

gcc -std=c17 -O2 -flto -c main.c -o main.o
gcc -std=c17 -O2 -flto -c util.c -o util.o
gcc -O2 -flto main.o util.o -o app

-flto allows optimization across translation units. Use it consistently for compile and link steps, then measure compile time, binary size, and performance.

Target-Specific Code Generation

gcc -O2 -march=native main.c -o app

-march=native may use instructions available only on the build machine. It is useful for local performance tests, but usually wrong for binaries distributed to different computers.


10. Coverage and Profiling

Code Coverage with gcov

gcc -std=c17 -O0 -g --coverage main.c -o app
./app
gcov main.c

--coverage instruments the program and produces files that gcov uses to show which source lines executed. Run representative tests before reading coverage.

Profile-Guided Optimization (PGO)

# 1. Build an instrumented program
gcc -O2 -fprofile-generate main.c -o app

# 2. Run realistic workloads
./app input.txt

# 3. Rebuild using measured behavior
gcc -O2 -fprofile-use main.c -o app

PGO is useful only when the training runs resemble real use. Keep profile data aligned with the same source and build configuration.


11. Preprocessor Workflows

Define Build Configurations

gcc -DDEBUG -DLOG_LEVEL=2 main.c -o debug_app
gcc -DNDEBUG -DAPP_VERSION='"1.2.0"' main.c -o release_app
#if defined(DEBUG)
    #define LOG(message) fprintf(stderr, "%s\n", message)
#else
    #define LOG(message) ((void)0)
#endif

Inspect Predefined Macros

gcc -dM -E - < /dev/null              # Unix shell: built-in C macros
gcc -std=c17 -dM -E - < /dev/null    # Include selected standard mode

On PowerShell, a comparable empty input pipeline is:

'' | gcc -std=c17 -dM -E -

Include Search and Macro Investigation

gcc -E -Iinclude src/main.c -o main.i
gcc -v -E -x c /dev/null             # Print configured include search paths on Unix
gcc -H -Iinclude -c src/main.c       # Trace headers being included

12. C Versus C++ with GCC

TaskCC++
Compile and linkgcc main.c -o appg++ main.cpp -o app
Standard-std=c17-std=c++20
Object compilegcc -c file.cg++ -c file.cpp
Link object files containing C++Prefer g++g++ *.o -o app

GCC can compile a .cpp file when invoked as gcc, but the final link step does not automatically add the C++ standard library. Use g++ for C++ executables:

g++ -std=c++20 main.cpp widget.cpp -o app
/* math_api.h */
#ifdef __cplusplus
extern "C" {
#endif

int add(int a, int b);

#ifdef __cplusplus
}
#endif

extern "C" prevents C++ name mangling for APIs implemented in C.


13. Hardening and Production Checks

For applications that accept untrusted input, compiler flags can add defense in depth. The suitable combination depends on target operating system, libc, deployment requirements, and performance budget.

gcc -std=c17 -O2 -Wall -Wextra \
  -fstack-protector-strong -D_FORTIFY_SOURCE=2 \
  -fPIE -pie main.c -o app
OptionPurpose
-fstack-protector-strongAdd stack corruption checks to more vulnerable functions
-D_FORTIFY_SOURCE=2Add some checked libc operations when optimization and libc support are available
-fPIE -pieBuild a position-independent executable for address randomization support
-Wl,-z,relro,-z,nowRequest additional ELF/Linux linker hardening

Sanitizers help find bugs during testing; hardening options help make some bugs harder to exploit in deployed builds. Neither replaces input validation, correct ownership, or testing.


14. Advanced Compiler Inspection

Ask GCC About Available Options

gcc --help=warnings
gcc --help=optimizers
gcc --help=target
gcc -Q -O2 --help=optimizers

-Q -O2 --help=optimizers is useful for inspecting which optimization switches GCC enables for the selected compiler and target.

Inspect Assembly Output

gcc -std=c17 -O2 -S main.c -o main.s
gcc -std=c17 -O2 -S -masm=intel main.c -o main.s  # Supported on x86 targets
gcc -std=c17 -O2 -fverbose-asm -S main.c -o main.s

Symbols and Binary Information on Unix-like Systems

nm app                  # List symbols
objdump -d app          # Disassemble
readelf -h app          # ELF header information
ldd app                 # Shared library dependencies on Linux

These commands are provided by binutils or the operating system rather than by GCC itself.


15. A Practical Makefile with GCC

CC := gcc
CPPFLAGS := -Iinclude
CFLAGS := -std=c17 -Wall -Wextra -Wpedantic -MMD -MP
LDLIBS :=

TARGET := app
SOURCES := src/main.c src/math_utils.c
OBJECTS := $(SOURCES:.c=.o)
DEPENDS := $(OBJECTS:.o=.d)

.PHONY: all debug release clean

all: debug

debug: CFLAGS += -g -Og -fsanitize=address,undefined -fno-omit-frame-pointer
debug: LDFLAGS += -fsanitize=address,undefined
debug: $(TARGET)

release: CFLAGS += -O2 -DNDEBUG
release: $(TARGET)

$(TARGET): $(OBJECTS)
	$(CC) $(LDFLAGS) $^ $(LDLIBS) -o $@

src/%.o: src/%.c
	$(CC) $(CPPFLAGS) $(CFLAGS) -c $< -o $@

clean:
	rm -f $(TARGET) $(OBJECTS) $(DEPENDS)

-include $(DEPENDS)

Run:

make debug
make clean
make release

For larger projects, build into a separate directory so debug and release object files cannot be accidentally mixed.


16. Common Errors and Fixes

Message or SymptomLikely CauseTypical Fix
fatal error: foo.h: No such file or directoryHeader search path missingAdd -Ipath/to/headers or fix include
undefined reference to 'foo'Declaration found, implementation not linkedAdd its .o file or -l library
undefined reference to 'sqrt'Math library not linked on Unix-like systemPut -lm after object/source files
multiple definition of 'x'Global definition placed in multiple files/headersPut extern declaration in header and one definition in a .c file
C++ undefined reference to std::...Linked C++ program using gccLink with g++
Program crashes only at runtimeMemory bug or undefined behaviorRebuild with -g -fsanitize=address,undefined
Debugger skips lines or variables vanishOptimization changes program layoutUse -Og or -O0 for debugging
Works locally, fails on another CPUBuilt with host-specific instructionsAvoid -march=native for distributed binaries
# Good: objects first, dependent libraries later
gcc main.o -L. -lutils -lm -o app

# Can fail with traditional static linking order
gcc -lutils -lm main.o -o app

17. Copy-Paste Build Recipes

C Development

gcc -std=c17 -Wall -Wextra -Wpedantic -Wconversion -g -Og main.c -o app

C Debugging with Sanitizers

gcc -std=c17 -Wall -Wextra -g -Og \
  -fsanitize=address,undefined -fno-omit-frame-pointer \
  main.c -o app

C Release

gcc -std=c17 -Wall -Wextra -O2 -DNDEBUG main.c -o app

C++ Development

g++ -std=c++20 -Wall -Wextra -Wpedantic -g -Og main.cpp -o app

Build with Headers and Multiple Files

gcc -std=c17 -Wall -Wextra -Iinclude \
  src/main.c src/io.c src/math_utils.c -o app
gcc -std=c17 -Wall -Wextra -Iinclude -c src/io.c -o io.o
gcc -std=c17 -Wall -Wextra -Iinclude -c src/main.c -o main.o
gcc main.o io.o -o app

18. Learning Path and Quick Recall

Beginner

  1. Compile one .c file with gcc file.c -o app.
  2. Always enable -Wall -Wextra and select a standard such as -std=c17.
  3. Learn what preprocessing, compilation, assembly, and linking do.
  4. Use -g -Og and a debugger instead of adding endless print statements.

Intermediate

  1. Split a program into headers and source files, compiling with -c.
  2. Link libraries with -L and -l, and understand link ordering.
  3. Add dependency generation using -MMD -MP in a Makefile.
  4. Run sanitizer builds regularly and fix every real diagnostic.

Advanced

  1. Inspect generated assembly and optimization choices.
  2. Measure -O2, -O3, LTO, and PGO rather than assuming they are faster.
  3. Build shared/static libraries and control their public API.
  4. Add platform-appropriate hardening and automated warning/sanitizer builds.

Recall Card

Build C:       gcc -std=c17 -Wall -Wextra file.c -o app
Build C++:     g++ -std=c++20 -Wall -Wextra file.cpp -o app
Compile only:  gcc -c file.c -o file.o
Link:          gcc main.o util.o -lm -o app
Debug:         gcc -g -Og file.c -o app
Sanitize:      gcc -g -Og -fsanitize=address,undefined file.c -o app
Release:       gcc -O2 -DNDEBUG file.c -o app
Preprocess:    gcc -E file.c -o file.i
Assembly:      gcc -O2 -S file.c -o file.s
Coverage:      gcc --coverage file.c -o app && ./app && gcov file.c

On this page