Skip to content

/cheatsheets/c/gcc-cheat-sheet

gcc cheat sheet: compile, warnings, debug, optimize, link and preprocess C code

verified onenvironmentlocal · linux 6.18.44-fc-v236 x64 · GNU bash 5.2.21updated
tool
C
versions
GCC 4.x – 15.x
os
linux, macos, windows

The gcc commands you need most often, grouped by the job they do. Each option is described in the GCC manual: overall options, warnings, debugging, optimization and linking.

TaskCommandNote
Build an executablegcc main.c -o appWithout -o the output is a.out
Compile only, no linkgcc -c util.cWrites util.o
Link object filesgcc main.o util.o -o appSeveral files: see the multi-file page
Pick the C standardgcc -std=c11 main.c -o appSee the -std values page
Run the result./appThe current directory is not on PATH

See compile multiple C files and which -std value to use.

Warnings

OptionEffect
-WallEnables the common warnings (despite the name, not all of them)
-WextraAdds more warnings, for example unused parameters
-pedanticWarns about code that is not valid ISO C for the chosen -std
-WerrorTurns every warning into an error and fails the build
-Wno-unused-parameterSwitches one warning off

Debug, optimize, sanitize

  • -g adds debug information so gdb shows source lines and variable names.
  • -O0 (default) does no optimisation, -O1, -O2 and -O3 optimise more, -Os optimises for size. Use -O0 -g while debugging, since optimised code reorders lines.
  • -fsanitize=address builds with AddressSanitizer, which stops on out-of-bounds access and use-after-free with a report. It is the quickest way to find the cause of a segmentation fault. -fsanitize=undefined catches undefined behaviour such as signed overflow.

Headers and libraries

OptionMeaningExample
-I DIRSearch DIR for header files-I include
-L DIRSearch DIR for libraries-L /opt/lib
-l NAMELink libNAME.so or libNAME.a-lm for the math library
-D NAME=VALUEDefine a macro-DDEBUG=1

Put -l options after the files that need them, because the linker reads its inputs in order.

Inspect the stages

bash
cat > hello.c <<'EOF'
#include <stdio.h>
#define GREETING "hello"
int main(void) { puts(GREETING); return 0; }
EOF
gcc -Wall -Wextra -std=c11 hello.c -o hello && ./hello
gcc -E -P hello.c | tail -n 1
gcc -S -o - hello.c | grep -c "call.*puts"
gcc -c hello.c && ls hello.o

Output

hello
int main(void) { puts("hello"); return 0; }
1
hello.o

-E stops after the preprocessor and prints the expanded source, -S stops after compilation and writes assembly, -c stops before linking. Reading the expanded output shows why a macro or an include behaves unexpectedly.

Common mistakes

  • Forgetting -o and then running the wrong old a.out.
  • Using -Wall as if it covered everything; add -Wextra.
  • Benchmarking a binary built with -O0 or sanitizers.
  • Placing -lm before the source file, which causes undefined reference to errors for math functions.

FAQ

What is the minimum gcc command to compile a C file?

gcc main.c -o app compiles main.c and links it into an executable called app. Without -o, gcc writes a.out. Add -Wall -Wextra so the compiler reports likely mistakes while you build.

Why do I put -lm after the source files?

The linker resolves libraries in the order given. If -lm comes before the object files that need it, symbols from those files are not yet known and you get undefined reference errors. Put -l options at the end.

What is the difference between -c and -o?

-c stops after compiling and writes an object file (.o) without linking. -o only sets the name of the output, whatever stage produces it. They are often used together: gcc -c util.c -o util.o.

Sources