Appearance
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
| Part | Reading and exploration |
|---|---|
| Ecosystem and execution model | 7–10 hours |
| Everyday C | 20–28 hours |
| Everyday modern C++ | 24–34 hours |
| Standards and portability | 8–12 hours |
| Build systems and IDEs | 14–20 hours |
| Dependencies and distribution | 10–15 hours |
| Quality and automation | 14–20 hours |
| Integrated project work | 10–15 hours |