/cheatsheets/c/gcc-cheat-sheet
gcc cheat sheet: compile, warnings, debug, optimize, link and preprocess C code
- 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.
Compile and link
| Task | Command | Note |
|---|---|---|
| Build an executable | gcc main.c -o app | Without -o the output is a.out |
| Compile only, no link | gcc -c util.c | Writes util.o |
| Link object files | gcc main.o util.o -o app | Several files: see the multi-file page |
| Pick the C standard | gcc -std=c11 main.c -o app | See the -std values page |
| Run the result | ./app | The current directory is not on PATH |
See compile multiple C files and which -std value to use.
Warnings
| Option | Effect |
|---|---|
| -Wall | Enables the common warnings (despite the name, not all of them) |
| -Wextra | Adds more warnings, for example unused parameters |
| -pedantic | Warns about code that is not valid ISO C for the chosen -std |
| -Werror | Turns every warning into an error and fails the build |
| -Wno-unused-parameter | Switches one warning off |
Debug, optimize, sanitize
-gadds debug information sogdbshows source lines and variable names.-O0(default) does no optimisation,-O1,-O2and-O3optimise more,-Osoptimises for size. Use-O0 -gwhile debugging, since optimised code reorders lines.-fsanitize=addressbuilds 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=undefinedcatches undefined behaviour such as signed overflow.
Headers and libraries
| Option | Meaning | Example |
|---|---|---|
| -I DIR | Search DIR for header files | -I include |
| -L DIR | Search DIR for libraries | -L /opt/lib |
| -l NAME | Link libNAME.so or libNAME.a | -lm for the math library |
| -D NAME=VALUE | Define a macro | -DDEBUG=1 |
Put -l options after the files that need them, because the linker reads its inputs in order.
Inspect the stages
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.oOutput
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
-oand then running the wrong olda.out. - Using
-Wallas if it covered everything; add-Wextra. - Benchmarking a binary built with
-O0or sanitizers. - Placing
-lmbefore the source file, which causesundefined reference toerrors 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.