Course Plan
A complete course in C: fifty-six weekly topics taking a reader from no prior programming experience to competent, independent, professional C development. This page sets out what the course covers, what it assumes, what it needs, and how it is built.
- 56 weekly topics in four levels of fourteen.
- Basic — the language core, ending with pointers and strings.
- Intermediate — memory, aggregate data, files, errors, modular design.
- Advanced — libraries and tooling, data structures, performance, portability, systems, networking, concurrency.
- Professional — codebases, collaboration, distribution, interoperability, security, embedded, maintenance.
1Aim
C is used in operating systems, embedded software, compilers, databases, and every performance-sensitive layer beneath higher-level languages. It gives direct control over memory representation and execution, and it gives no protection against getting that control wrong.
The aim of this course is therefore not only to teach the language — that is the first fourteen weeks — but the discipline that makes writing C in production tractable: warnings treated as defects, sanitizers run by default, every return value checked, ownership stated in every interface, and the difference between what happens to work and what is actually guaranteed.
Each topic assumes only what earlier topics have established. Nothing is used before it is explained, and the chain of dependencies is deliberate: pointers arrive before strings, memory layout before recursion, structures before the standard library that uses them.
2Prerequisites
No prior programming experience is assumed. What is assumed:
- Comfort creating, saving, and organizing files, and basic terminal navigation.
- Arithmetic, and the ability to break a task into ordered steps.
- A computer running Linux, macOS, or Windows with WSL.
Two preparatory documents are available: prerequisites for preparation and key figures who shaped the field.
3Learning outcomes
| After | You can |
|---|---|
| Basic (1–14) | Write, build, format, debug and version a C program; explain how values are represented; use every control structure; work with pointers, arrays and strings. |
| Intermediate (15–28) | Manage heap memory without leaking; design aggregate types; read and write files; define an error contract; split a program into modules with a hidden implementation. |
| Advanced (29–42) | Build and ship libraries; write generic code; implement the standard data structures; profile and optimize with evidence; avoid undefined behavior; write portable, networked and concurrent programs. |
| Professional (43–56) | Work in an unfamiliar codebase; review C for memory safety; distribute a library with a stable ABI; call it from other languages; fuzz it; write bare-metal firmware; maintain code that outlives its authors. |
4Tooling
Everything used in the course is free and cross-platform. Nothing requires physical hardware.
| From week | Tool | Purpose |
|---|---|---|
| 1 | GCC or Clang, a text editor | Compiling |
| 3 | Git, clang-format | Version control, formatting |
| 12 | AddressSanitizer, UBSan | Memory and undefined-behavior detection |
| 20 | Valgrind | Leaks, uninitialized reads |
| 29 | Make, CMake, nm, objdump | Building, inspecting binaries |
| 34 | perf, Compiler Explorer | Profiling, reading generated code |
| 35 | GDB, gcov, -fanalyzer | Debugging, coverage, static analysis |
| 48 | libFuzzer, AFL++ | Fuzzing |
| 49 | arm-none-eabi-gcc, QEMU, gdb-multiarch | Cross-compiling and running bare-metal firmware |
The embedded block needs no hardware. Weeks 49 to 55 target an ARM Cortex-M image running under QEMU, so every example — including the interrupt timing, the linker layout, and the debugger sessions — can be built and run on any laptop. The same code and the same GDB commands work unchanged against a real board with a debug probe.
A single command line is used throughout and introduced in week 2:
gcc -std=c17 -Wall -Wextra -g -fsanitize=address,undefined -o prog prog.c5How each week is structured
Every week's notes follow the same shape, so the material can be navigated without re-reading:
- What you can do by the end — five concrete capabilities.
- The concepts — several numbered sections, with diagrams where a picture carries the idea.
- A worked example — a complete, compilable program with the commands to build and run it, and experiments that break it deliberately to show the failure mode.
- Common mistakes — a table of what goes wrong, what the symptom looks like, and the fix.
- Check yourself — five questions with answers hidden until you have tried them.
- Where this leads — the connection to the following week.
The worked examples are the spine of the course. They are not exercises to be submitted; they are the artifact the notes build, and they are meant to be typed, compiled, and broken.
6The chain of examples
The examples are deliberately connected, so that each week extends something already understood rather than starting over:
week 11 a swap function that cannot work
week 13 the same function, fixed with pointers
week 19 a growable array on the heap
week 20 the same array, seeded with five memory defects
week 28 the same array as a module with a hidden implementation
week 29 the same module as a static and a shared library
week 30 the same container, made generic over any type
week 45 the same library, versioned and installable
week 46 the same library, called from Python, Rust and C++
week 23 a validating input parser
week 48 the same parser, attacked by a fuzzer
week 40 a TCP server, one forked process per connection
week 47 the same server, rewritten as a single-threaded event loop
week 49 a bare-metal image printing over a UART
week 50 the same UART, as a driver written against the register map
week 51 the same driver, interrupt-driven
week 55 the same driver, behind a HAL and unit-tested on the host7Outline
Basic — the language core
Intermediate — memory, data, and structure
Advanced — tooling, systems, and scale
Professional — practice, distribution, and embedded
8Scope
Two boundaries are worth stating explicitly.
The course targets C17 by default, with C23 features identified where they differ. C89 and C99 are covered historically in week 2 because a great deal of existing code is written in them.
The hosted material assumes a POSIX environment — Linux, macOS, or WSL. Weeks 39, 40, 41 and 47 use POSIX interfaces that are not part of standard C; this is stated wherever it applies. Weeks 49 to 55 are freestanding and assume no operating system at all.
Not covered: C++ (a different language with different idioms), graphical interfaces, and language-specific build ecosystems beyond Make and CMake.
9References
| Kind | Source |
|---|---|
| Reference | cppreference — C; version-specific and accurate |
| Tutorial | Beej's Guide to C Programming |
| Questions | comp.lang.c FAQ |
| Standard | WG14 — the working drafts are freely available |
| Tools | GCC, GDB, Valgrind, Compiler Explorer |
| Practice | Learn-C.org, Exercism C track |
| Code to read | musl libc, SQLite, Lua, Redis, git — week 42 |
Week 24 covers how to read a manual page and the text of the standard, which is the skill these references exist to support.