Module 2: Memory, Pointers & Machine Representation
Primary texts: The C Programming Language (K&R) for pointers, arrays, and structs, and Computer Organization and Design (Patterson & Hennessy) for signed-number and floating-point representation Selective support: CODE (Petzold) for first-principles bits/bytes and memory, with brief visits to external references (cppreference, the GNU malloc manual, and Drepper's memory paper) when a concept needs reinforcement
This guide is the primary teacher. You do not need to read the source books front-to-back to complete this module. You do need to become operationally strong at reading bit patterns, manipulating addresses, reasoning about memory layout, and defending programs against memory errors.
Scope of This Module
This module is not a C-syntax review. It is where the machine stops being abstract.
What it covers in depth:
- binary, hexadecimal, and the byte as the unit of addressable memory
- unsigned and two's-complement integer representation, overflow, and wraparound
- IEEE 754 floating-point: sign, exponent, mantissa, special values, and rounding
- pointers as typed addresses, dereference, and the
&/*operators - pointer arithmetic with its implicit multiplication by
sizeof(T) - pointers to pointers, arrays of pointers, and function pointers as first-class control
- the virtual address space: text, rodata, data, bss, heap, and stack segments
- stack frames, calling conventions, and activation records
- heap allocation with
malloc/free, fragmentation, and allocator families - buffer overflows, out-of-bounds access, and stack smashing
- use-after-free, double-free, and dangling pointers
- detecting errors with AddressSanitizer, Valgrind, and static analyzers
- struct layout with padding and alignment, bit fields, and packed structs
- endianness: big- vs little-endian, and what it means for serialization
What it deliberately does not try to finish here:
- full CPU pipelines, cache design, and virtual memory hardware (Module 3)
- operating-system process structure beyond the address space view (Semester 5)
- exploitation and hardening specifics such as ROP, CFI, or KASLR (later security work)
- allocator implementation at production quality (you will sketch one, not ship one)
This is the machine-representation foundation that Modules 3-5 and all later systems work rely on.
Before You Start
Answer these closed-book before starting the main path:
- Why does the C type of a pointer matter if all pointers "just hold an address"?
- If
int x = -1;on a 32-bit machine, what is the hex pattern in memory and why? - What is the difference between the address of a local variable and the address of a
malloced block? - Why does
*(p + 1)not always move one byte? - What is the difference between a dangling pointer and an uninitialized pointer?
Diagnostic Interpretation
4-5 solid answers
- You are ready for the full path.
2-3 solid answers
- Continue, but expect extra time in the pointer-arithmetic and memory-layout clusters.
0-1 solid answers
- Revisit Module 1 (C Programming Fundamentals). This module assumes you can write, compile, and run small C programs from the terminal.
What This Module Is For
Memory representation is the language every later systems claim is written in. Later work repeatedly asks:
- why did this program crash with a segmentation fault and no error message?
- why is this integer suddenly negative after one more addition?
- why do two
==-equal floats compare unequal after a round trip? - why does the same struct take 12 bytes in one place and 16 in another?
- why does a one-byte overwrite crash a seemingly unrelated function?
This module builds the representation fluency needed for:
- operating systems (page tables, process memory, system calls)
- networking (byte order, packet layout, wire formats)
- compilers and assemblers (calling conventions, ABIs, relocations)
- security (memory-safety bugs and their mitigations)
- performance work (cache lines, struct packing, SIMD alignment)
You are learning to see what the CPU sees.
Concept Map
How To Use This Module
Work in order. The later clusters only make sense if the earlier representation habits are stable.
Cluster 1: Bits, Bytes, and Representation
| Order | Concept | Type | Focus |
|---|---|---|---|
| 1 | Binary, Hex, and the Byte as the Unit of Access | PRIMARY | Why memory is addressed in bytes and why hex is the working notation |
| 2 | Integer Representations: Unsigned, Two's Complement, Overflow | PRIMARY | How signed numbers fit in a fixed-width byte pattern and where they break |
| 3 | Floating-Point IEEE 754: Sign, Exponent, Mantissa, Special Values | PRIMARY | Why 0.1 + 0.2 != 0.3 and what NaN, Inf, and subnormals are for |
Cluster mastery check: Can you take an arbitrary hex pattern and say what it means as an unsigned int, a signed int, and a float?
Cluster 2: Pointers and Addresses
| Order | Concept | Type | Focus |
|---|---|---|---|
| 4 | Pointers: Addresses, Dereference, & and * | PRIMARY | Pointers as typed addresses, not mysterious references |
| 5 | Pointer Arithmetic and the Type-Scaled Step | PRIMARY | Why p + 1 moves by sizeof(*p) bytes |
| 6 | Pointers to Pointers, Arrays of Pointers, Function Pointers | PRIMARY | Indirection as a design tool and control as data |
Cluster mastery check: Can you draw a memory diagram for int **pp = &p; and predict what each dereference yields?
Cluster 3: Memory Layout
| Order | Concept | Type | Focus |
|---|---|---|---|
| 7 | The Virtual Address Space: Text, Data, BSS, Heap, Stack | PRIMARY | Where different kinds of data live and why it matters |
| 8 | Stack Frames, Calling Conventions, Activation Records | PRIMARY | How a function call builds and tears down memory |
| 9 | Heap Allocation: malloc, free, Fragmentation, Allocators | PRIMARY | Where malloc memory comes from and why freeing is not just cleanup |
Cluster mastery check: Given a C program, can you classify where each variable lives and predict its lifetime?
Cluster 4: Memory Errors and Safety
| Order | Concept | Type | Focus |
|---|---|---|---|
| 10 | Buffer Overflows, Out-of-Bounds Access, and Stack Smashing | PRIMARY | How one extra byte can corrupt a frame and redirect control |
| 11 | Use-After-Free, Double-Free, Dangling Pointers | PRIMARY | Why lifetimes, not just pointers, are the real discipline |
| 12 | Detecting Errors: ASan, Valgrind, Static Analyzers | SUPPORTING | Tools that make invisible bugs visible |
Cluster mastery check: Given a short buggy C program, can you predict whether ASan, Valgrind, or -Wall will catch it?
Cluster 5: Structs, Alignment, and Endianness
| Order | Concept | Type | Focus |
|---|---|---|---|
| 13 | Struct Layout, Padding, and Alignment | PRIMARY | Why sizeof(struct) is not always the sum of its fields |
| 14 | Endianness: Big- vs Little-Endian and Serialization | SUPPORTING | Why raw struct dumps never travel across machines |
| 15 | Bit Fields, Bit Manipulation Idioms, and Packed Structs | SUPPORTING | Precise bit-level layout for protocols, hardware, and flags |
Cluster mastery check: Given a struct definition, can you compute its size on a 64-bit machine without running it?
Then work these practice pages:
| Order | Practice path | Focus |
|---|---|---|
| 1 | Bits and Representation Lab | Hex, two's complement, overflow, and IEEE 754 drills |
| 2 | Pointers and Arithmetic Workshop | Dereference, pointer arithmetic, and function pointers |
| 3 | Memory Layout and Errors Clinic | Address-space reading, stack frames, and ASan/Valgrind triage |
| 4 | Code Katas | Linked list, toy malloc, stack-frame tracer, struct-packing analyzer, endianness converter |
Use Module Quiz after the concept and practice path. Use Reference and Selective Reading and Learning Resources only for targeted reinforcement.
Learning Objectives
By the end of this module you should be able to:
- Convert fluently between binary, hex, and decimal, and name the byte as the unit of memory access.
- Read and write two's-complement integers and predict overflow and wraparound in C expressions.
- Decode an IEEE 754
floatordoublefrom its bit pattern and explain special values. - Write and reason about pointer code, including
&,*, pointer arithmetic, and function pointers. - Draw a memory diagram with stack, heap, globals, and text, and place variables correctly.
- Trace a function call's effect on the stack including saved registers and the return address.
- Implement and reason about
malloc/freeat a sketch level, including fragmentation. - Identify buffer overflow, use-after-free, and double-free patterns and explain how each can be exploited.
- Use AddressSanitizer, Valgrind, and compiler warnings to locate memory bugs.
- Compute struct layout including padding, and write correct code across endianness boundaries.
Outputs
- a representation notebook with at least 20 solved bit-pattern conversions (unsigned, signed, float)
- a pointer drill sheet with at least 15 memory diagrams you drew before running the code
- a one-page walkthrough of a stack frame for a small function, annotated with saved registers and return address
- a toy
malloc/freeimplementation (bump allocator and free-list) with a short written analysis of fragmentation - a debugging log with at least three bugs that ASan or Valgrind located, including the command line and final fix
- a struct-packing analyzer: given a struct, predict
sizeofand each field's offset, and verify withoffsetof - an endianness converter that round-trips
uint32_tanddoubleacrosshtonl/ntohl-style calls - a mistake journal naming at least 12 memory-related reasoning errors (
off-by-one on buffer size,signed overflow is UB,stale pointer afterrealloc``,freed but still in list, etc.) - a short memo connecting this module to operating systems, compilers, and security work
Completion Standard
You have completed Module 2 when all of these are true:
- you can translate a hex dump to integers, floats, and pointer targets without a reference
- you can draw a pointer diagram before writing the code, not after
- you can predict the segment and lifetime of every variable in a small C program
- you can sketch a function's stack frame with saved registers, return address, and locals
- you can explain
malloc/freeat a level that includes fragmentation and alignment - you have used ASan or Valgrind to find at least one real bug and can reproduce the workflow
- you can compute struct size and alignment in your head for common field orderings
- you can explain endianness in words that a network-protocol writer would accept
If the program "runs on your machine" but you cannot explain where each byte lives, the module is not complete.
Reading Policy
- Concept pages are the main path.
- Local book chunks are selective reinforcement, not a second syllabus.
Read only if stuckmeans try the concept page, self-check, and drill first.Optional deep divemeans additional nuance or exercise volume, not required progression.- Because memory bugs are expensive, written memory diagrams and lifetime arguments are required, not optional enrichment.
Suggested Weekly Flow
| Day | Work |
|---|---|
| 1 | Concepts 1-3 and a 10-line bit/hex/float conversion sheet |
| 2 | Concepts 4-6 and at least three memory diagrams drawn before running any code |
| 3 | Concepts 7-9 and one stack-frame trace on paper |
| 4 | Concepts 10-12 and one buggy program run under ASan and Valgrind |
| 5 | Concepts 13-15 and one struct-packing exercise with offsetof |
| 6 | Practice pages 1-2 and targeted local-book reinforcement |
| 7 | Practice page 3 and one kata |
| 8 | Remaining katas, quiz, and mistake-log cleanup |
Reference
If you need exact links into the local chunked books, use Reference and Selective Reading.
The Memory Allocator tutorial is the perfect concretization of this module: ownership, alignment, headers, fragmentation — all in 500 lines of C. See Build Your Own X overview.
Rich Learning Pages
Worked Examples | Guided Labs | Case Studies | Mistake Clinic | Reading Guide | Capstone Thread