Ads

CS50x 2026 – Lecture 4 – Memory

CS50 Lecture 4 explores memory management, pointers, hexadecimal, strings, malloc, and file I/O in C programming.

By CS50
⏱ 2h 19min 👁 83,895 views 📅 January 1, 2026

More from this course

Free Computer Science Course

Lesson 6 of 13

Summary

Understanding Memory in Computer Systems

CS50's Lecture 4 on Memory represents a fundamental shift in computer science education, moving from high-level abstractions to the concrete realities of how data is stored and manipulated in a computer's memory. This comprehensive 140-minute lecture, taught by David J. Malan at Harvard University, demystifies the relationship between code and hardware, introducing students to concepts that are essential for writing efficient, secure, and properly functioning programs. The lecture begins by establishing why memory matters: understanding how variables are stored, accessed, and managed is crucial for debugging, optimizing performance, and preventing common programming errors that lead to security vulnerabilities. Through hands-on examples and visual demonstrations, the lecture breaks down abstract concepts into digestible pieces, making memory management accessible to learners at any level.

Hexadecimal and Memory Representation

Before diving into pointers and dynamic memory allocation, the lecture introduces hexadecimal notation, the universal language used by programmers to represent memory addresses and binary data in a human-readable format. Hexadecimal (base-16) serves as a bridge between decimal numbers that humans naturally understand and the binary representation that computers use internally. Students learn why hexadecimal is preferred in computer science: it compresses binary data more efficiently than decimal and aligns naturally with byte boundaries, making it ideal for describing memory addresses, color values in graphics, and data structures. The lecture demonstrates practical applications, such as how pixel art can be represented in hexadecimal, connecting abstract notation to tangible visual outputs and reinforcing the principle that everything in memory is ultimately just numbers encoded in a specific format.

The Concept of Pointers and Memory Addresses

Pointers represent one of the most challenging yet powerful concepts in computer programming, and this lecture dedicates significant time to building intuition around them. A pointer is simply a variable that stores a memory address—a location in RAM where data is stored. The lecture explains the two fundamental pointer operators: the ampersand (&), which retrieves the address of a variable, and the asterisk (*), which dereferences a pointer to access the data at that address. Through visual demonstrations and code examples, students learn that pointers are not magical or mysterious but rather straightforward tools for manipulating memory directly. The lecture emphasizes that pointers enable powerful programming patterns: storing references to data, creating dynamic data structures like linked lists and trees, and writing functions that modify variables indirectly. Understanding pointers is essential for advanced programming tasks and provides insight into how higher-level languages manage memory behind the scenes.

Strings as Arrays and Memory Layout

Strings in C are not primitive types but rather arrays of characters, and this distinction carries profound implications for how they are stored and manipulated in memory. The lecture explores how a string like "Hello" is represented as a contiguous block of memory, with each character occupying one byte and a null terminator () marking the end. This representation explains why string operations in C require careful attention to memory boundaries and why functions like strlen must scan for the null terminator. The lecture compares C's approach to strings with higher-level languages that abstract away these details, illustrating how understanding the underlying memory layout enables more efficient and safer code. Students also learn pointer arithmetic—the ability to increment or decrement a pointer to move through memory sequentially—which is particularly useful when iterating through strings or arrays. This section bridges the gap between simple data types and complex data structures, showing how primitive concepts combine to create useful abstractions.

Dynamic Memory Allocation with malloc

One of the lecture's most critical topics is dynamic memory allocation using malloc (memory allocation), the function that allows programs to request memory from the heap at runtime. Unlike stack memory, which is automatically managed and has a fixed size determined at compile time, heap memory is explicitly allocated and deallocated by the programmer. The lecture explains why this distinction matters: stack memory is fast but limited, while heap memory is vast but requires careful management. Students learn the malloc function's signature and return value—a pointer to the newly allocated memory—and the importance of checking whether malloc succeeded before using the returned pointer. The lecture demonstrates practical use cases, such as creating arrays whose size is not known until runtime, and emphasizes that malloc and free must be paired correctly to prevent memory leaks. This section also introduces valgrind, a powerful debugging tool that detects memory errors, helping students identify and fix memory-related bugs before they cause problems in production systems.

Common Memory Pitfalls and Debugging

The lecture dedicates substantial attention to the mistakes programmers commonly make when managing memory, providing diagnostic techniques and tools to catch these errors. Garbage values—uninitialized variables that contain arbitrary data from previous memory usage—can cause unpredictable program behavior if not handled carefully. Buffer overflows occur when a program writes data beyond the allocated boundary, potentially corrupting adjacent memory or enabling security exploits. The lecture uses the "Pointer Fun with Blinky" interactive demonstration to visualize how pointer misuse can corrupt memory, making abstract concepts tangible and memorable. Students learn about valgrind, a dynamic analysis tool that monitors memory usage and reports leaks, double-frees, and out-of-bounds accesses. The lecture also covers swapping—exchanging the values of two variables—and demonstrates why naive approaches fail without pointers and why correct implementations require passing addresses. These sections emphasize that memory errors are not merely academic concerns but serious issues that affect program reliability and security, motivating the importance of careful, disciplined coding practices.

Input Handling and File Operations

The final segment of the lecture addresses practical input and output operations, beginning with scanf, a function for reading formatted input from the user. The lecture explains scanf's syntax, common pitfalls (such as forgetting the ampersand operator for non-pointer types), and why scanf can be error-prone compared to alternatives. Students then explore file I/O operations—reading from and writing to files on disk—which extend the principles of memory management and data manipulation beyond the program's runtime. The lecture demonstrates how to open files, read or write data, and properly close files to free resources. This section connects memory concepts to persistent storage, showing how data can be saved to disk and retrieved later, and illustrating that the principles of pointer manipulation and careful resource management apply equally to file operations. By the lecture's conclusion, students understand that memory management is not an advanced topic but a foundational skill applicable across virtually all programming tasks.

Building Intuition for Systems Programming

Beyond the specific topics, CS50 Lecture 4 cultivates a deeper mental model of how computers actually work. By understanding memory, pointers, and dynamic allocation, students transition from thinking of programming as manipulation of abstract values to recognizing it as direct interaction with hardware resources. This perspective shift enables more informed decisions about code design, performance optimization, and debugging. The lecture's comprehensive table of contents—spanning from pixel art and hexadecimal through file I/O—demonstrates how seemingly disparate concepts connect through a common underlying principle: all computation ultimately involves reading, manipulating, and writing data in memory. Students who master these concepts gain not only the technical skills to write correct C programs but also the conceptual foundation to understand how higher-level languages operate, how security vulnerabilities arise, and how to design efficient algorithms and data structures. This lecture represents a pivotal moment in computer science education where theory meets practice, and students develop the mental models necessary for advanced work in systems programming, embedded systems, and computer security.

What you will learn

  • Understand how memory addresses and hexadecimal notation work in computer systems
  • Use pointers to access and manipulate memory directly in C programs
  • Manage strings as character arrays and perform pointer arithmetic
  • Allocate and deallocate dynamic memory with malloc and free
  • Debug memory errors using tools like valgrind and understand common pitfalls
  • Implement file I/O operations and handle input with scanf

Concepts covered

Technologies used

Chapters 16 markers

  1. Introduction
  2. Pixel Art
  3. Hexadecimal
  4. Memory
  5. Pointers
  6. Strings
  7. Pointer Arithmetic
  8. String Comparison
  9. Copying and malloc
  10. Valgrind
  11. Garbage Values
  12. Pointer Fun with Blinky
  13. Swapping
  14. Overflow
  15. scanf
  16. File I/O

Next suggested video

Reviews

Student rating 0.0
0 reviews
Rate this lesson

Help other students decide if this lesson is useful.

No reviews yet. Be the first to rate this lesson.