Pointers are one of the most important concepts in low-level programming.
Up until now, we have primarily worked with values:
int age = 28;
In this example, the variable contains the value 28.
A pointer is different. Instead of storing a value directly, a pointer stores the memory address of another object.
For example:
int age = 28;
int* ptr = &age;
Here:
age = 28
ptr = address of age, e.g. 0x1000
Conceptually:
Address Value
0x1000 28
ptr = 0x1000
Notice that the pointer does not contain the number 28. It contains the location where 28 is stored.
This ability to reference memory locations directly is one of the reasons C remains so important in operating systems, malware, exploit development and security research.
Dereferencing
If a pointer contains an address, how do we access the value stored at that address?
This process is known as dereferencing.
Consider:
int age = 28;
int* ptr = &age;
Memory might look like:
Address Value
0x1000 28
ptr = 0x1000
Using the dereference operator (*):
printf("%d", *ptr);
The program:
- Reads the address stored inside
ptr - Goes to that memory location
- Retrieves the value stored there
Output:
28
Visually:
ptr
│
▼
0x1000 ──► 28
This is one of the most common patterns you will encounter while debugging applications and analyzing memory.
Why Pointers Matter
Pointers are everywhere.
Many concepts we have already discussed either directly use pointers or are built upon them:
- Arrays
- Strings
- Structs
- Functions
For example:
int numbers[5] = {10, 20, 30, 40, 50};
Internally, array access is often performed using pointer arithmetic.
Pointers become especially important in security because many vulnerabilities involve incorrect handling of memory addresses. Buffer overflows, use-after-free vulnerabilities, arbitrary read/write primitives and many exploit techniques ultimately revolve around manipulating pointers or the memory they reference.
For now, the key takeaway is simple:
A variable stores a value. A pointer stores the location of a value.