R2/7.1 - Review & Arrays (2026-10-07)
Watch on YouTube →
Overview
Chris Bourke reviews C fundamentals for an upcoming 25-question exam, including declarations, integer division, loops, pointers, pass-by-reference, and unit testing. He then introduces arrays, explains zero-based indexing and the dangers of out-of-bounds access, and demonstrates why large arrays should use heap memory allocated with malloc rather than limited stack space.
Key takeaways
- C integer division truncates toward zero, so `10 / 20` evaluates to 0 rather than 0.5 when both operands are integers.
- For an array with n elements, valid indices are 0 through n−1; using index n or a negative index invokes undefined behavior even if the program does not immediately crash.
- A 10-million-element integer array needs about 40 MB when integers occupy four bytes, which exceeds the example environment's 8 MB stack limit.
- Dynamic allocation requests bytes, so an array of N integers should use a size calculation such as `N * sizeof(int)` rather than a hard-coded byte count.
- Uninitialized local array elements are indeterminate, not automatically zero; their observed values can vary across executions.
- Out-of-bounds access is not reliably caught by standard warning flags, so memory-analysis tools such as Valgrind are useful for finding these errors.
Chapters
0:00
Opening Audio and Return to the Exam Review
- Music plays through the opening before Chris Bourke addresses an audio issue at about 2:27.
- The class resumes with multiple-choice review questions on C syntax and program behavior.
2:27
Reviewing C Declarations, Integer Division, and Loop Counts
- The valid declaration is `int A = 50;`; examples fail for reasons including using a number as a variable name or omitting a semicolon.
- With integer values A=10, B=0, and C=20, `A / C` truncates to 0, making both the division comparison and `C - A == A + B` true.
- A `while` loop starting at 0 and incrementing by 2 through 10 prints six lines.
5:06
Tracing Pointers, Pass-by-Reference, Enums, and For Loops
- In a function receiving an integer by value and a pointer, changing the local copy leaves X at 5 while dereferencing the pointer changes Y to 20; the returned sum makes Z equal 30.
- Pointer parameters are the parameters declared with `*`; those are the values passed by reference in the examples.
- A valid enum declaration separates members with commas, and the loop example prints 2, 4, 6, and 8 because J remains 2.
11:17
Older Exam Questions on Addresses and Pointer Dereferencing
- The address operator `&` obtains a variable's memory address, while `*P = 10` changes the value at the address held by pointer P.
- Assigning 10 directly to a pointer attempts to use 10 as an address; dereferencing an uninitialized pointer can access an invalid location.
- A pointer set to `&A` is non-null, so a test for `X == NULL` does not print its conditional message.
15:23
Practicing Unit Testing and Syntax Checks with CS50.ai
- CS50.ai can generate practice questions, but its unit-testing prompts repeat across sessions and sections.
- Unit tests check a function or component in isolation; edge cases matter because unusual inputs can expose bugs, and deterministic tests return the same result for the same input.
- A generated C exercise illustrates a missing semicolon and the difference between assignment with `=` and comparison with `==`.
- The exam has 25 questions, opens the next morning, and can be completed Thursday, Friday, or Sunday.
22:19
Array Elements, Zero-Based Indexing, and Bounds
- A C array holds elements of one type under one identifier, with square brackets and an integer index used to access each element.
- For an array of n elements, valid indices run from 0 through n−1; `argv[0]` is the executable name.
- Array elements occupy contiguous memory, so an index acts like an offset from the first element.
- Negative indices and index n are out of bounds and can cause undefined behavior, crashes, or memory corruption.
27:29
Static Arrays, Stack Limits, and Uninitialized Values
- A declaration such as `int array[10]` creates a static array on the stack; its last valid element is `array[9]`.
- The standard iteration pattern starts at 0, continues while `i < 10`, and increments by 1.
- Only explicitly assigned elements—42 at index 0 and 101 at index 9 in the example—have known values; uninitialized stack elements are not guaranteed to be zero.
- Reading or writing outside the array can appear to work temporarily but remains undefined behavior.
35:14
Stack Smashing and the Limits of Large Static Arrays
- Writing past the end of a 10-element array can corrupt nearby stack memory and eventually trigger a stack-smashing failure.
- With 4-byte integers, one million elements require about 4 MB and fit within the demonstrated 8 MB stack limit, while 10 million require about 40 MB and overflow it.
- Stack capacity varies by environment and may be only a few megabytes or even kilobytes in embedded systems.
38:18
Heap Allocation with malloc, size_t, and sizeof
- Dynamic arrays use heap memory, which can support larger allocations than the stack, though the operating system may deny a request.
- `malloc` requests a number of bytes and returns a generic `void *`; `size_t` represents the requested byte count.
- Use `sizeof(int)` or the relevant type's `sizeof` result to calculate allocation sizes instead of assuming every C integer is four bytes.
- A typed pointer can then refer to the allocated memory; the lecture demonstrates converting the returned pointer to an integer pointer.
45:03
Building a Dynamic Integer Array and Checking Memory Errors
- The demonstration allocates space for 10 million integers with `malloc(N * sizeof(int))`, then successfully stores 42 at index 0 and 101 at index N−1.
- Oversized allocation requests can fail or overflow their byte-count calculation, so allocation size must be handled carefully.
- Dynamic arrays still require valid indices; nearby out-of-bounds accesses may go undetected because memory is allocated in pages.
- Compiler flags such as `-Wall` and `-Wextra` do not reliably catch bounds violations; Valgrind is introduced as a tool for detecting memory errors.
Summary, takeaways, and chapters were generated by AI from the video's transcript and may contain errors. The video belongs to its creator, Chris Bourke.