Pointers and Memory Addresses
After completing this topic, you will:
Understand that a pointer is a variable that stores a memory address, and know why it is important in computer science and how it is hidden in high-level languages.
Where do variables live?
When a program runs, variables are stored in memory. Memory is a sequence of bytes, each with a unique number. This number is the memory address.
Memory address: 0x1000 0x1004 0x1008 0x100C
ββββββββββββββββββββββββββββββββ
β 42 ββ 7 ββ 'A' ββ 0 β
ββββββββββββββββββββββββββββββββ
Variable a Variable b Variable c Variable dWhen you write a = 42, the computer stores the value 42 somewhere in memory, and associates the name a with that location. We don't need to worry about the address; we just use the name a.
Pointers: variables that store addresses
Regular variables store values. Pointers store the address of another variable.
int a = 42; // Store 42 in a
int *p = &a; // Store the address of a in p
printf("%d\n", a); // 42 (the value of a)
printf("%p\n", p); // 0x1000 (the address of a)
printf("%d\n", *p); // 42 (the value at the address pointed to by p)Variable a Pointer p
ββββββββββββ ββββββββββββ
β 42 β β 0x1000 ββββ Points to a
ββββββββββββ ββββββββββββ
Address: 0x1000 Address: 0x2000&aβ get the address of a (address-of)*pβ dereference p (get the value at the address p points to)
Why do we need pointers?
1. Efficiently pass large data
Suppose you have an array of 10 million numbers and want to pass it to a function. Copying the entire array would be wasteful in terms of memory and time. Passing just the address allows you to access the original data directly.
2. Dynamic data structures
Linked lists, trees, graphs β these data structures need to store the "location of the next node". That "location" is a pointer.
Node A Node B Node C
ββββββ¬βββββββββ ββββββ¬βββββββββ ββββββ¬βββββββ
β 10 β 0x2000 βββββ 20 β 0x3000 βββββ 30 β NULL β
ββββββ΄βββββββββ ββββββ΄βββββββββ ββββββ΄βββββββ3. Modify the original in a function
void swap(int *a, int *b) {
int temp = *a;
*a = *b;
*b = temp;
}
int x = 10, y = 20;
swap(&x, &y);
// x = 20, y = 10Without pointers, if you pass values by copy, any changes made inside the function will not affect the original variables. Pointers allow you to modify the original data.
Dangerous pointers
Null pointers
int *p = NULL;
printf("%d", *p); // Crash! (Segmentation Fault)Dereferencing a pointer that points to nothing will crash your program. This is called a null pointer dereference β one of the most costly types of bugs in the history of bugs.
Dangling pointers
int *p = malloc(sizeof(int));
*p = 42;
free(p); // Return the memory
printf("%d", *p); // Memory has already been freed β unpredictableAfter freeing the memory using free, if you access the memory at that address, you might get garbage values or the program might crash.
Pointers in high-level languages
High-level languages like Python, JavaScript, and Java do not let you work with pointers directly. However, the same concept exists under the name references.
# References in Pythona = [1, 2, 3]b = a # b "references" the same listb.append(4)print(a) # [1, 2, 3, 4] β the original is also modifiedIn Python, variables are essentially pointers. However, there is no syntax like & or *, and you cannot directly manipulate memory addresses. The problem discussed in the previous Python topic (reference propagation of mutable objects) is related to this.
| C Pointers | Python References | |
|---|---|---|
| Direct access to address | Yes | No |
| Pointer arithmetic | Yes (p + 1) | No |
| NULL crash | Yes | None β AttributeError |
| Manual memory deallocation | Required (free) | Automatic (garbage collection) |
High-level languages hide pointers and make them safer. The trade-off is that you lose the ability to directly control memory.
Key takeaways
Pointers are variables that store memory addresses. They are necessary for passing large data, implementing dynamic data structures, and modifying the original data in a function. Python/JavaScript "references" are a safer way to achieve the same thing as pointers β you can't manipulate addresses directly, but the underlying principle is the same.