C/C++ Project Tutorials in the Project-Based Learning Repository: 32 Hands-On Guides
The practical-tutorials/project-based-learning repository curates 32 comprehensive C/C++ project tutorials ranging from operating system kernels and JIT compilers to game engines and databases, all indexed in the central README.md file.
The project-based-learning repository by practical-tutorials serves as a curated collection of hands-on programming resources. Its README.md catalog links to external, self-contained C/C++ tutorials that walk you through building real-world applications from scratch, covering systems programming, language implementation, graphics, and low-level hardware interaction.
Systems Programming & Operating Systems
These tutorials teach low-level concepts by building kernels, shells, and system utilities.
Write a Shell in C teaches you to build a minimal Unix shell with job control. You will implement process creation using fork/exec, handle pipelines, and manage signal handling. The tutorial demonstrates how modern shells manage child processes and user input.
Write an OS from scratch (tuhdo/os01) and How to create an OS from scratch (cfenollosa/os-tutorial) provide complementary paths to building a minimal operating system kernel. These cover bootstrapping, protected mode entry, VGA drivers, interrupt handling, paging, and multitasking. Let’s Write a Kernel focuses specifically on booting real hardware with paging and a basic scheduler.
Write a Bootloader in C explains the 16-bit real-mode startup sequence, using BIOS interrupts for disk I/O and switching to protected mode. Write a FUSE Filesystem moves to user-space, teaching you to implement getattr, read, and write operations to mount custom filesystems on Linux.
Linux Container in 500 Lines of Code demonstrates modern systems programming by implementing a tiny container runtime using namespaces and cgroups. You will handle process isolation, filesystem setup, and resource management without relying on Docker or containerd.
Compilers, Interpreters & Language Tools
This category covers language implementation from scratch, including JIT compilation and static analysis.
Build an Interpreter (Crafting Interpreters) dedicates chapters 14-15 to writing a full-featured interpreter for the Lox language in C. You will implement lexing, parsing, bytecode generation, and a complete virtual machine with memory management.
Write a C compiler by Nora Sandler is a ten-part series covering the entire compiler pipeline. Starting from integer lexing and code generation, it progresses through unary/binary operators, local variables, conditionals, loops, functions, and global variables. Let’s write a compiler by Brian Callahan offers an alternative eight-part series focusing on lexer and parser implementation, code generation, and I/O handling.
Implementing a Language with LLVM guides you through building "Kaleidoscope," a toy language using LLVM’s infrastructure. You will construct intermediate representation (IR), implement a JIT compiler, and apply optimization passes.
Writing a minimal x86-64 JIT compiler in C++ (Parts 1 and 2) teaches runtime code generation. You will emit machine code directly to executable memory pages, handle memory protection with mmap, and implement register allocation and function calling conventions.
Build Your Own Lisp focuses on interpreter construction in C, covering S-expressions, symbol tables, REPL implementation, and garbage collection. Build an Interpreter from the Crafting Interpreters book provides additional coverage of VM design and bytecode execution.
Databases, Data Structures & Storage Engines
Learn persistent storage and efficient data structures through practical implementation.
Let’s Build a Simple Database builds a SQLite-like database from scratch using C. You will implement B-Tree storage, query parsing, and transaction logging. Implementing a Key-Value Store creates a persistent key-value database using file I/O, hashing, and log-structured storage techniques.
Write a hash table in C by James Routley provides a complete implementation of a dynamic hash map. You will handle collision resolution through chaining, implement automatic resizing, and design a clean C API.
Build Your Own Redis with C/C++ guides you through creating an in-memory key-value store with networking support. You will implement an event loop, handle client connections, and add persistence features.
Game Development, Graphics & Emulation
These projects range from retro console emulation to 3D software rasterization.
Building a CHIP-8 Emulator teaches you to build an emulator for the classic CHIP-8 virtual machine. You will decode opcodes, manage graphics buffers, and implement timing and input handling. How to Program an NES Game in C focuses on 6502-based development, covering low-level graphics, input handling, and timing loops for classic Nintendo hardware.
The Tiny 3D graphics projects collection includes four distinct implementations:
- Tiny Renderer: A 500-line software rasterizer mimicking the OpenGL pipeline with vertex transformation and Z-buffering
- Understandable RayTracing: A 256-line bare C++ ray-tracer implementing ray-sphere intersection and recursive shading
- KABOOM!: A 180-line C++ game engine demo featuring entity-component systems and physics
- 486 lines of C++: A Wolfenstein-style ray-caster FPS implementing texture mapping and collision detection
Beginning Game Programming with C++ and SDL provides a series of 2D game tutorials (Pong, Breakout) using the SDL library. You will learn window creation, rendering loops, event handling, and audio integration. Space Invaders from Scratch offers a five-part series on building the classic arcade shooter, covering game loops and sprite handling. Tetris Tutorial in C++ implements a platform-independent clone focusing on game state machines and collision detection.
Meta Crush Saga demonstrates advanced C++17 metaprogramming by creating a compile-time generated game using templates and constexpr evaluation.
Developer Tools & Utilities
Build the tools that developers use daily.
Build Your Own Text Editor ("kilo") creates a terminal editor in approximately 1000 lines of C. You will handle raw terminal mode, buffer management, and scrolling. Write a Live Code-reloader Library for C++ implements hot-reloading using dynamic linking and symbol lookup, allowing you to swap compiled modules at runtime.
Writing a Linux Debugger is a ten-part series covering ptrace system calls, breakpoint insertion, ELF and DWARF parsing, stack unwinding, and source-level stepping. High-Performance Matrix Multiplication implements optimized GEMM routines using cache blocking and SIMD intrinsics.
Write Your Own Virtual Machine builds a VM for the LC-3 assembly language, teaching instruction decoding, stack management, and I/O handling. Learning KVM – Implement Your Own Linux Kernel focuses on virtualization, running a custom kernel under KVM with device emulation.
Code Examples to Get Started
Below are minimal starting points derived from the tutorials to illustrate key concepts.
Minimal Text Editor (C)
From the Build Your Own Text Editor tutorial, this snippet demonstrates raw terminal mode:
#include <stdio.h>
#include <unistd.h>
#include <termios.h>
struct termios orig_termios;
void disableRawMode(void) {
tcsetattr(STDIN_FILENO, TCSAFLUSH, &orig_termios);
}
void enableRawMode(void) {
tcgetattr(STDIN_FILENO, &orig_termios);
atexit(disableRawMode);
struct termios raw = orig_termios;
raw.c_lflag &= ~(ECHO | ICANON);
tcsetattr(STDIN_FILENO, TCSAFLUSH, &raw);
}
int main(void) {
enableRawMode();
char c;
while (read(STDIN_FILENO, &c, 1) == 1 && c != 'q') {
write(STDOUT_FILENO, &c, 1);
}
return 0;
}
Hash Table Implementation (C++)
From the Write a hash table tutorial, a basic chaining approach:
#include <list>
#include <vector>
#include <string>
#include <iostream>
template <typename K, typename V>
class HashMap {
static const size_t BUCKET_COUNT = 16;
std::vector<std::list<std::pair<K,V>>> buckets;
public:
HashMap() : buckets(BUCKET_COUNT) {}
void put(const K& key, const V& value) {
auto& bucket = buckets[std::hash<K>{}(key) % BUCKET_COUNT];
for (auto& kv : bucket) {
if (kv.first == key) { kv.second = value; return; }
}
bucket.emplace_back(key, value);
}
V* get(const K& key) {
auto& bucket = buckets[std::hash<K>{}(key) % BUCKET_COUNT];
for (auto& kv : bucket) {
if (kv.first == key) return &kv.second;
}
return nullptr;
}
};
JIT Compiler Skeleton (C++)
From the Writing a minimal x86-64 JIT compiler tutorial:
#include <sys/mman.h>
#include <cstring>
#include <cstdio>
int main() {
void* code = mmap(nullptr, 4096,
PROT_READ | PROT_WRITE | PROT_EXEC,
MAP_ANONYMOUS | MAP_PRIVATE, -1, 0);
// mov eax, 42 ; ret
unsigned char instr[] = {0xB8, 42, 0, 0, 0, 0xC3};
memcpy(code, instr, sizeof(instr));
int (*func)() = (int(*)())code;
printf("Result: %d\n", func());
return 0;
}
Summary
- The practical-tutorials/project-based-learning repository indexes 32 C/C++ tutorials in its
README.mdfile. - Tutorials span systems programming (OS kernels, containers, shells), language implementation (compilers, JIT engines), storage engines (databases, key-value stores), and graphics (software rasterizers, emulators).
- Each tutorial is a self-contained external resource linked from the repository, ranging from single-page implementations to multi-part series.
- Code examples demonstrate core concepts including terminal control, hash table collision resolution, and runtime code generation.
Frequently Asked Questions
Are these C/C++ tutorials suitable for beginners?
Most tutorials assume familiarity with C or C++ syntax and basic computer science concepts like pointers and memory management. However, projects like Build Your Own Text Editor and Write a hash table are specifically designed as introductory systems programming exercises, while compiler and OS tutorials typically require intermediate knowledge.
Do I need Linux to complete these projects?
Many tutorials, particularly those involving FUSE filesystems, Linux containers, ptrace-based debuggers, and kernel development, require a Linux environment or virtual machine. However, graphics projects using SDL, text editors, and some compilers can be completed on macOS or Windows with minimal modification.
Where are the actual tutorial source files located?
The repository does not host the tutorial content directly. All 32 C/C++ tutorials are linked from the README.md file at the repository root, pointing to external blog posts, GitHub repositories, and documentation sites maintained by the original authors.
How can I contribute a new C/C++ project to the repository?
Contributions are managed through the repository's CONTRIBUTING.md guidelines. To add a new tutorial, submit a pull request modifying the README.md to include the project title, description, and direct link, ensuring the tutorial provides step-by-step instructions for building a working C or C++ application.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →