Skip to content

C and C++ Course Curriculum

This course teaches C, modern C++, and the native-development toolchain to programmers already comfortable with Swift, Java, or C#. It moves quickly through familiar control flow and abstraction concepts, then develops the less familiar machinery: object lifetimes, undefined behavior, translation units, linking, ABIs, build graphs, dependency discovery, and cross-platform toolchains.

The learning format and editorial rules live in ARTICLE_GUIDE.md; declared baselines live in SUPPORT_MATRIX.md.

Part 1: Languages, implementations, and the path to a program

1. What C and C++ actually are

Separates the two ISO languages from implementations, standard libraries, operating-system APIs, and third-party libraries. Introduces hosted and freestanding implementations and establishes why shared syntax does not make C a subset of modern C++.

2. From source code to a running program

Follows preprocessing, compilation, assembly, linking, loading, and execution. Introduces translation units, headers, object files, symbols, executables, static libraries, shared libraries, and the difference between compile, link, load, and runtime failures.

3. Compilers and platform toolchains

Explains GCC, Clang/LLVM, Apple Clang, MSVC, clang-cl, and MinGW-w64; compiler drivers; target triples; standard libraries; ABIs; language-mode flags; diagnostics; and practical compiler selection.

4. Setting up a development environment

Compares Visual Studio, Xcode, CLion, VS Code, and terminal-first setups. Covers PATH, compiler discovery, SDKs, extensions, project settings, and a repeatable environment check.

Part 2: Everyday C

5. Values, declarations, expressions, and control flow

Covers declarations, scalar types, literals, operators, blocks, selection, loops, functions at first use, and the distinction between expressions and statements. Slows down for integer division, promotions, sequence rules, and side effects.

6. The C type system and conversions

Covers integer ranks, signedness, floating types, qualifiers, casts, implicit conversion, _Bool, size_t, fixed-width types, and the usual arithmetic conversions.

7. Pointers, arrays, and memory layout

Builds a precise model of addresses, pointer arithmetic, arrays, decay, multidimensional arrays, alignment, object representation, aliasing, and pointer validity.

8. Functions, headers, translation units, and linkage

Develops declarations versus definitions, prototypes, parameter passing, function pointers and stateful callback conventions, variadic functions, internal and external linkage, static, extern, include guards, preprocessing, _Generic, and stable header design.

9. Structs, unions, enumerations, and bit fields

Covers aggregate and compound-literal initialization, layout and padding, tagged unions, enum limitations, bit fields, flexible array members, and opaque-handle APIs.

10. Strings, bytes, and text encodings

Explains null-terminated byte strings, length-aware buffers, common library functions, formatting, parsing, character encodings, and safe boundary policies.

11. Dynamic memory and ownership conventions

Covers allocation, resizing, deallocation, ownership transfer, borrowing, cleanup paths, arenas, double frees, leaks, dangling pointers, and API documentation conventions.

12. The C standard library and operating-system boundaries

Maps headers and facilities for I/O, files, time, signals, nonlocal control transfer, locale, threads, and atomics, then separates ISO C from POSIX and Windows APIs.

13. Undefined, unspecified, and implementation-defined behavior

Explains the categories that make implementation freedom possible, with engineering policies for overflow, bounds, initialization, lifetime, aliasing, shifts, and diagnostics.

Part 3: Everyday modern C++

14. C++ as its own language

Shows which C knowledge transfers and which habits should change. Establishes value semantics, deterministic cleanup, the standard library, stronger types, and the risks of treating C++ as C with classes.

15. Values, references, initialization, and const

Covers initialization forms, references, auto, const, named casts, constant evaluation, value categories at a useful level, copies, moves, and parameter-passing choices.

16. Classes, invariants, and special member functions

Covers class layout, access, constructors, destructors, copy/move operations, the rules of zero/three/five, operator overloading, comparisons, inheritance, virtual dispatch, and object slicing.

17. RAII, ownership, and smart pointers

Develops deterministic resource management, scopes, unique_ptr, shared_ptr, weak_ptr, non-owning views, lifetime hazards, and why raw pointers need not mean ownership.

18. Containers, iterators, algorithms, and ranges

Teaches standard containers by invalidation, complexity, and ownership; then connects iterators, algorithms, views, and C++20 ranges.

19. Templates, concepts, and generic programming

Covers function and class templates, deduction, instantiation, overload resolution, ADL, type traits, class template argument deduction, constraints, concepts, variadic templates, specialization, compile-time diagnostics, and source organization.

20. Errors, exceptions, optional values, and results

Compares exceptions, error_code, system_error, optional, variant, and expected-style results; covers result propagation, stack unwinding, exception safety, noexcept, and boundary translation.

21. Lambdas and callable design

Covers captures, closure lifetime, generic lambdas, function objects, std::function, callback ownership, and composing algorithms without hiding mutation.

22. Concurrency, atomics, and the memory model

Introduces threads, mutexes, condition variables, futures, cooperative stopping, atomics, happens-before, data races, and why volatile is not synchronization.

Part 4: Standards, compatibility, and portability

23. C versions in practice

Traces C89/C90, C99, C11, C17, and C23; identifies major language and library additions; explains conformance modes, GNU dialects, optional facilities, and gradual adoption.

24. C++ versions in practice

Traces C++98/03 through C++11, 14, 17, 20, and 23, with a forward-looking treatment of C++26 work. Covers feature-test macros, implementation support, migrations, and selecting a project baseline.

25. Portability, ABIs, and platform differences

Covers data models, endianness, object formats, name mangling, calling conventions, symbol visibility, runtime libraries, POSIX versus Windows, source versus binary compatibility, and cross-language C interfaces.

Part 5: Building programs

26. Manual builds that expose every layer

Builds programs, static libraries, and shared libraries with direct compiler, archiver, and linker-driver commands. Explains include paths, library paths, macros, dependency files, command ordering, inspection tools, and debug/release flags.

27. Make and incremental builds

Covers targets, prerequisites, recipes, variables, automatic variables, pattern rules, generated dependencies, parallel builds, phony targets, configurations, and Make's boundary as a low-level build graph.

28. Modern CMake

Covers configure/generate/build/test/install phases, targets, usage requirements, scopes, generators, presets, toolchain files, dependencies, install/export rules, and single- versus multi-config workflows.

29. Visual Studio and integrated build workflows

Explains solutions, projects, MSBuild, configurations, platforms, property pages, debugger integration, native versus CMake projects, and equivalent concepts in Xcode, CLion, and VS Code.

Part 6: Dependencies and library distribution

30. Why native package management is different

Explains source versus binary packages, headers and link artifacts, ABI compatibility, transitive usage requirements, system packages, vendoring, submodules, and reproducibility.

31. vcpkg, Conan, FetchContent, and pkg-config

Demonstrates manifest-mode vcpkg, Conan profiles and generators, CMake FetchContent, find_package, pkg-config, system managers, NuGet's niche, lockfiles, registries, and binary caches.

32. Designing and distributing libraries

Covers public headers, API/ABI design, static/shared choices, visibility, semantic versioning limits, CMake package configuration, installation layouts, exported targets, and consumer tests.

Part 7: Testing, diagnosis, and automation

33. Testing C and C++

Covers lightweight C tests, CTest, GoogleTest, Catch2, doctest, test doubles, integration tests, deterministic resource tests, and testing installed artifacts.

34. Debugging with GDB, LLDB, and Visual Studio

Covers debug information, optimization effects, breakpoints, stepping, stack frames, threads, watches, core dumps, and debugger-specific interfaces built over common concepts.

35. Warnings, sanitizers, and static analysis

Covers warning policies, AddressSanitizer, UndefinedBehaviorSanitizer, ThreadSanitizer, MSVC diagnostics, Valgrind, clang-tidy, static analyzers, false positives, and CI integration.

36. Formatting, linting, and editor integration

Covers clang-format, EditorConfig, compilation databases, clangd, IntelliSense, include analysis, pre-commit checks, and keeping editor behavior aligned with the build.

37. Profiling and performance measurement

Covers benchmarks, optimization levels, sampling and instrumentation, platform profilers, allocation and cache behavior, compiler output inspection, and measurement discipline.

38. Cross-compilation, CI, and reproducible builds

Covers build/host/target systems, sysroots, CMake toolchain files, containers, CI matrices, compiler caches, artifacts, dependency caches, deterministic inputs, and release builds.

Part 8: Putting the system together

39. Project structure and architectural boundaries

Organizes applications and libraries around targets and dependency direction, separating public headers, private implementation, platform adapters, tests, tools, generated code, and build output.

40. Choosing a practical toolchain

Provides reasoned defaults for Windows applications, portable libraries, small Unix utilities, embedded systems, teaching projects, and large monorepos without pretending one stack fits all.

41. Case study: a portable library and CLI

Builds one modest C library, a modern C++ wrapper and CLI, tests, installation rules, dependency metadata, presets, diagnostics, and CI. The same artifacts are first built manually and then expressed as CMake targets.

42. Reading and modernizing an unfamiliar project

Develops a safe reconnaissance and modernization sequence: find entry points, identify the build graph and ABI boundaries, reproduce builds, enable diagnostics, add characterization tests, update standards deliberately, and replace ownership hazards incrementally.

Approximate pacing

PartReading and exploration
Ecosystem and execution model7–10 hours
Everyday C20–28 hours
Everyday modern C++24–34 hours
Standards and portability8–12 hours
Build systems and IDEs14–20 hours
Dependencies and distribution10–15 hours
Quality and automation14–20 hours
Integrated project work10–15 hours