← Back to C series
🚀
Getting Started
gcc · Make · per-OS install · compile flags

Getting Started — Environment & Build

The first step of CLI-based C learning. Install **gcc · Make** per OS, build a single file, and learn debug flags & Makefile in one go.

gccMakesetupflags
Duration
1-2 hours
Level
📊 Beginner
Prerequisite
🎯 None (basic terminal use)
Outcome
A working gcc/Make environment + learning-friendly build flags

What you'll learn

  • 1Install gcc and Make on Linux/macOS/Windows and verify versions.
  • 2Build `hello.c` with `gcc` and run `./hello`.
  • 3Understand the common compile flags (`-Wall`, `-g`, `-O2`, `-std=c11`).
  • 4Write a minimal `Makefile` for a single-file project.

Development environment

This repository was verified on:

ItemVersion
OSLinux (Ubuntu 24.04)
Compilergcc 13.3.0
StandardC11 (`-std=c11`)
Build toolGNU Make

Verify your environment

bash
which gcc                       # /usr/bin/gcc
gcc --version                   # gcc 13.3.0
gcc -print-prog-name=cc1        # actual cc1 path
gcc -print-search-dirs          # search paths
make --version

Install per OS

OSInstall commandDefault path
Ubuntu / Debian`sudo apt install build-essential``/usr/bin/gcc`
Fedora / RHEL`sudo dnf install gcc make``/usr/bin/gcc`
macOS (Homebrew)`brew install gcc``/opt/homebrew/bin/gcc-14` (Apple Silicon)
macOS (Xcode CLI)`xcode-select --install``/usr/bin/gcc` (clang underneath)
Windows (MSYS2 UCRT64)`pacman -S mingw-w64-ucrt-x86_64-gcc``C:\msys64\ucrt64\bin\gcc.exe`
Windows (MinGW-w64)use installer`C:\mingw64\bin\gcc.exe`

Beginner recommendation — one per OS

OSRecommendedHow to install
**Windows****MSYS2 (UCRT64)** — latest GCC + easy updatesrun installer, then `pacman -S mingw-w64-ucrt-x86_64-gcc`
**macOS****Xcode Command Line Tools** — `gcc` is clang, good enough for learning`xcode-select --install`
**Linux (Ubuntu/Debian)****build-essential**`sudo apt install build-essential`

Editor: **VS Code** + the C/C++ extension is recommended — debugger, autocomplete, build all wired up.

Core Concepts

1) Single-file build

bash
gcc -std=c11 -Wall hello.c -o hello
./hello
FlagWhy
`-std=c11`Pin to C11 standard
`-Wall`Turn on common warnings (always use this)
`-Wextra`Even more warnings
`-g`Embed debug info (for `gdb`)
`-O0` / `-O2`Optimization off / on
`-o name`Set output filename

2) Minimal Makefile

makefile
CC = gcc
CFLAGS = -std=c11 -Wall -Wextra -g

hello: hello.c
	$(CC) $(CFLAGS) $< -o $@

clean:
	rm -f hello

Run with `make`. `make clean` removes the output.

3) Debug build vs release build

PurposeFlags
Debug (development)`-g -O0 -Wall -Wextra`
Release (deployment)`-O2 -DNDEBUG`

Mixing the two on the same binary makes line-stepping confusing — pick one.

How a C program is built — the four stages

`gcc hello.c -o hello` looks like one step, but it runs four stages in order. Knowing them makes error messages far less mysterious — most "weird" errors belong to a specific stage.

StageWhat it doesTypical error
Preprocess (`-E`)Expands `#include` / `#define`, strips comments`No such file or directory` (missing header)
Compile (`-S`)C → assembly; type checks & warnings happen here`implicit declaration`, type warnings
Assemble (`-c`)Assembly → object file (`.o`)rare (bad inline asm)
LinkJoins object files + libraries into the executable`undefined reference to ...`

So `undefined reference` is a **link** error (a library wasn't linked, or a function was never defined), while `implicit declaration` is a **compile** error (a missing prototype). Same command, different stages.

bash
gcc -E hello.c -o hello.i   # 1. preprocess only
gcc -S hello.i -o hello.s   # 2. compile to assembly
gcc -c hello.s -o hello.o   # 3. assemble to an object file
gcc hello.o -o hello        # 4. link into an executable
💡

Add `-Wall -Wextra` and actually read the warnings — most beginner bugs (uninitialized variables, printf format mismatches) are caught here for free, before the program ever runs.

Examples

Example 1 — `hello.c`: build example from the main README — build with gcc then run ./hello

c
#include <stdio.h>
int main(void) {
    printf("Hello, World!\n");
    return 0;
}

**Output**

text
Hello, World!

Key: this single command does everything — `gcc hello.c -o hello && ./hello`.

Common Mistakes (FAQ)

Q. `gcc: command not found` — what now?

gcc isn't installed or isn't on your PATH. Install it first (`build-essential` on Ubuntu/Debian, Xcode Command Line Tools on macOS, MSYS2 UCRT64 on Windows), then re-open the terminal so the PATH refreshes.

Q. I ran `gcc hello.c` but there's no `hello` file — why?

Without `-o name`, gcc names the output `a.out` (or `a.exe` on Windows). Use `gcc hello.c -o hello`, and run it with `./hello` — on Linux/macOS the current directory isn't on PATH, so the leading `./` is required.

Q. `undefined reference to 'sqrt'` even though I `#include <math.h>`.

Including a header only *declares* the function; you must also *link* its library: `gcc prog.c -o prog -lm`. This is a link-stage error, not a compile error — the four-stage table above shows why.

Q. Do I really need `-std=c11`? It compiles without it.

gcc defaults to a standard (often gnu17) that quietly allows extensions. Pinning `-std=c11` keeps your code portable and predictable, and combined with `-Wall -Wextra` it warns when you drift into non-standard usage.

Q. Why do my breakpoints / line numbers look wrong in the debugger?

You likely built with optimization (`-O2`) or without `-g`. For debugging use `-g -O0`; optimization reorders and inlines code so source lines no longer map 1:1. Keep debug and release builds separate.

Recap

  • One command: `gcc -std=c11 -Wall file.c -o name && ./name`.
  • `-Wall` is non-negotiable in development.
  • Use a tiny Makefile early; you'll add to it later.

Try it

bash
echo '#include <stdio.h>\nint main(void){printf("Hello\n");return 0;}' > hello.c
gcc -std=c11 -Wall hello.c -o hello && ./hello

💻 Examples

Compilable, runnable examples — see the output yourself.

hello.cbuild example from the main README — build with gcc then run ./hello
CODE
#include <stdio.h>

int main(void) {
    printf("Hello, World!\n");
    return 0;
}
▶ Output
Hello, World!
Example code / lecture materials

All lecture materials and example code are openly available on GitHub.

View on GitHub ↗