GCC
GNU Compiler Collection — the workhorse of open-source C++ development. Widest platform and architecture support, mature optimizer, de-facto Linux standard.
TL;DR
GCC is the de-facto C++ compiler on Linux and the only serious choice for many embedded architectures. Use GCC 13+ for full C++23 partial support and GCC 14+ for improved C++23 conformance. Prefer -O2 for release builds and always pair with ASan/UBSan during development.
# Install (Ubuntu/Debian)
sudo apt install gcc-14 g++-14
# Compile
g++-14 -std=c++23 -O2 -Wall -Wextra -o myapp main.cpp
# With sanitizers (dev builds)
g++-14 -std=c++20 -O1 -fsanitize=address,undefined -fno-omit-frame-pointer -o myapp main.cppStandards support
| Standard | Status | Flag |
|---|---|---|
| C++11 | Full | -std=c++11 |
| C++14 | Full | -std=c++14 |
| C++17 | Full | -std=c++17 |
| C++20 | Full (GCC 13+) | -std=c++20 |
| C++23 | Partial (GCC 14+) | -std=c++23 |
| C++26 | In progress | -std=c++26 |
Use --std=c++20 (or c++17) as your minimum in new projects. Avoid c++0x/c++1y — those are legacy spellings.
Essential flags
Warning flags
# Recommended baseline
-Wall -Wextra -Wpedantic
# Stronger — catches more real bugs
-Wall -Wextra -Wpedantic -Wshadow -Wconversion -Wsign-conversion \
-Wnull-dereference -Wdouble-promotion -Wformat=2
# For header-only libs (treat warnings as errors)
-WerrorOptimization flags
-O0 # No optimization — fast compilation, best for debugging
-O1 # Minimal optimization — good for sanitizer builds
-O2 # Standard release — best balance (use this)
-O3 # Aggressive — more vectorization, sometimes slower due to code size
-Os # Optimize for size (embedded)
-Og # Debug-friendly optimization (GCC only)Debugging
-g # Include debug info (DWARF)
-g3 # Include macro definitions too
-ggdb # GDB-specific extensions
-fno-omit-frame-pointer # Keep frame pointer for profilers/sanitizersLink-time optimization
# Enable LTO (major win for release builds)
g++ -O2 -flto -fuse-linker-plugin -o myapp main.cpp lib.cpp
# Thin LTO (parallel, faster than full LTO)
g++ -O2 -flto=auto -o myapp main.cpp lib.cppArchitecture targets
GCC supports more target architectures than any other compiler:
# Cross-compile for ARM (embedded)
arm-none-eabi-g++ -std=c++20 -mcpu=cortex-m4 -mfpu=fpv4-sp-d16 -mfloat-abi=hard \
-Os -fno-exceptions -fno-rtti -o firmware.elf main.cpp
# RISC-V
riscv64-unknown-elf-g++ -march=rv64imafd -mabi=lp64d -o app main.cpp
# WebAssembly (via Emscripten, which uses LLVM internally but has GCC-compatible flags)
em++ -std=c++20 -O2 -o app.wasm main.cppSanitizers
# AddressSanitizer (heap/stack buffer overflows, use-after-free)
-fsanitize=address
# UndefinedBehaviorSanitizer (signed overflow, null deref, etc.)
-fsanitize=undefined
# ThreadSanitizer (data races)
-fsanitize=thread
# Combine ASan + UBSan (most useful combination)
-fsanitize=address,undefined -fno-omit-frame-pointerNote: ASan and TSan are mutually exclusive.
Useful diagnostics flags
# Show include paths resolved
-H
# Show where a macro is defined
-fdump-macro-expansion
# Show compilation time breakdown
-ftime-report
# Preprocessor output only
-E
# Assembly output (readable)
-S -fverbose-asmCMake integration
cmake_minimum_required(VERSION 3.20)
project(myapp CXX)
set(CMAKE_CXX_STANDARD 20)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
add_executable(myapp main.cpp)
# Apply warning flags
target_compile_options(myapp PRIVATE
$<$<CXX_COMPILER_ID:GNU>:-Wall -Wextra -Wpedantic -Wshadow>
)
# Enable LTO for Release builds
set_target_properties(myapp PROPERTIES INTERPROCEDURAL_OPTIMIZATION_RELEASE ON)GCC vs Clang — when to prefer GCC
| Situation | Prefer |
|---|---|
| Linux target, embedded (ARM/RISC-V) | GCC |
| macOS development | Clang |
| Best error messages | Clang |
| Widest architecture support | GCC |
| clang-tidy / clang-format | Clang |
| Maximum LTO performance on x86 | Similar |
| RISC-V, MIPS, PowerPC | GCC |
In practice, testing against both GCC and Clang in CI is the best approach — they catch different issues.
Common pitfalls
Implicit function declarations: GCC historically warned about these; in C23 they're errors. Always use proper headers.
Integer overflow: GCC assumes signed integer overflow doesn't happen (UB). Use -fwrapv only if you need wrap-around semantics.
Strict aliasing: GCC optimizes based on strict aliasing rules. Use -fno-strict-aliasing with caution — it disables a real optimization.
-O3 regressions: -O3 enables more aggressive transformations that can hurt performance due to code size increases. Profile before choosing -O3 over -O2.