C for programmers who want to understand how computers actually work — why C and its four-stage compilation model (preprocess, compile, assemble, link; declarations vs definitions), types/variables/operators (fixed-width integers, signedness hazards, integer promotion, bitwise ops), control flow and functions (pass-by-value, the call stack, scope and lifetime), pointers (addresses, dereference, pointer arithmetic, NULL, pointer-to-pointer — the heart of C), arrays/strings/memory-layout (array-to-pointer decay, null-terminated strings, buffer overflows), dynamic memory management (stack vs heap, malloc/calloc/realloc/free, ownership, leaks/use-after-free/double-free, Valgrind), structs/unions/data-structures (typedef, padding, tagged unions, building a linked list), and the preprocessor, undefined behavior, and safe-C idioms. Rounds out the language-series set alongside Go, Python, Rust, and TypeScript.
C is fifty years old and still runs the world — operating systems, databases, language runtimes, embedded devices, and the standard libraries under almost everything else. Learning C is learning how computers actually work: memory, pointers, and the thin layer between your code and the machine. This series builds C from the ground up, and it starts with what C is and what really happens when you compile it.
C is fifty years old and still runs the world — operating systems, databases, language runtimes, embedded devices. Learning C is learning how computers actually work: memory, pointers, and the thin layer between your code and the machine. This series builds C from the ground up, starting with what C is and what really happens when you compile it.
In C, a type is a promise about how many bytes a value occupies and how to interpret them. There's no hidden bignum, no automatic string, no safety rail — just fixed-width integers, floating-point, and the bit patterns underneath. Understanding C's types means understanding sizes, signedness, and the surprising rules of integer promotion, because in C the difference between `int` and `unsigned` can be the difference between correct and catastrophically wrong.
In C, a type is a promise about how many bytes a value occupies and how to interpret them — no hidden bignum, no safety rail, just fixed-width integers and the bits underneath. Understanding C's types means understanding sizes, signedness, and the surprising rules of integer promotion, where the difference between int and unsigned can be catastrophic.
C's control flow is the ancestor of the syntax you already know — `if`, `while`, `for`, `switch`. Its functions look familiar too, but they hide a defining C fact: arguments are passed by value, always copied. Understanding pass-by-value, and the call stack that makes function calls work, is the bridge to the hardest and most important topic in C — pointers.
C's control flow is the ancestor of the syntax you already know, and its functions look familiar too — but they hide a defining C fact: arguments are passed by value, always copied. Understanding pass-by-value, and the call stack that makes function calls work, is the bridge to the hardest and most important topic in C: pointers.
Pointers are the heart of C, the feature that makes it powerful and the one that makes it dangerous. A pointer is just a variable that holds a memory address — but that simple idea is how C functions modify their callers, how arrays and strings work, how dynamic memory is managed, and how data structures are built. Everything hard and everything essential in C runs through pointers.
Pointers are the heart of C — the feature that makes it powerful and the one that makes it dangerous. A pointer is just a variable holding a memory address, but that simple idea is how C functions modify their callers, how arrays and strings work, how dynamic memory is managed, and how data structures are built. Everything essential runs through pointers.
Arrays and strings in C are where the pointer model from the last post becomes concrete — and where C's most infamous security bugs live. An array is a contiguous block of memory whose name decays to a pointer; a string is just an array of characters with a null terminator and no length field. Understanding both, and the buffer overflows they invite, is essential C literacy.
Arrays and strings are where the pointer model becomes concrete — and where C's most infamous security bugs live. An array is a contiguous block whose name decays to a pointer; a string is just a char array with a null terminator and no length field. Understanding both, and the buffer overflows they invite, is essential C literacy.
Stack memory is automatic but rigid — sized at compile time and gone when a function returns. For data whose size you only know at runtime, or that must outlive the function that created it, C gives you the heap and four functions to manage it: `malloc`, `calloc`, `realloc`, and `free`. With that power comes C's heaviest responsibility: every allocation you make, you must free — exactly once, and never use again.
Stack memory is automatic but rigid. For data whose size you only know at runtime, or that must outlive its function, C gives you the heap and four functions: malloc, calloc, realloc, and free. With that power comes C's heaviest responsibility: every allocation you make, you must free — exactly once, and never use again.
Structs let you bundle related data into a single named type — the closest C gets to an object. Combined with pointers and heap allocation, they're how you build every data structure C is famous for: linked lists, trees, hash tables. This post covers structs, their cousins unions and enums, the memory-layout details that bite (padding), and puts it all together to build a linked list from scratch.
Structs let you bundle related data into a single named type — the closest C gets to an object. Combined with pointers and heap allocation, they're how you build every data structure C is famous for: linked lists, trees, hash tables. This post covers structs, unions, enums, the padding that bites, and builds a linked list from scratch.
Two things separate C programmers who ship reliable code from those who ship time bombs: understanding the preprocessor (the text-substitution pass that runs before compilation) and respecting undefined behavior (the operations C says have no defined meaning at all). This closing post covers both, plus the multi-file structure of real programs and the idioms that keep C safe — turning the whole series into a working discipline.
Two things separate C programmers who ship reliable code from those who ship time bombs: understanding the preprocessor (the text-substitution pass before compilation) and respecting undefined behavior (operations C says have no meaning at all). This closing post covers both, multi-file programs, and the idioms that keep C safe.
This series is part of a larger body of work by Pratik Dhanave, an Agentic AI Architect writing about production AI systems, distributed systems, and cloud-native engineering. Explore all course series, browse every post, or find topics via the tag index.