How the Dereference Operator Works in C
This article explains how the dereference operator (*)
retrieves data from memory in the C programming language. It covers the
relationship between pointers and physical memory addresses, the
critical role a pointer's data type plays in determining how many bytes
are read, and the low-level machine instructions executed by the CPU to
load that stored data into a usable variable.
In the C programming language, computer memory (RAM) is treated as a
linear sequence of sequentially numbered byte cells, each possessing a
unique memory address. A pointer variable does not hold standard
application data directly; instead, it stores one of these numerical
memory addresses. The dereference operator, denoted by the asterisk
symbol (*), instructs the compiler to bypass the pointer's
own location and directly access the contents held at the memory address
the pointer contains.
To retrieve data successfully, the dereference operator relies on two critical pieces of information: the starting memory address and the data type of the pointer. The address identifies where the data begins in memory. The data type tells the compiler two things: how many contiguous bytes to read from that starting point, and how to interpret the resulting binary pattern (such as an integer, a floating-point number, or an ASCII character).
For example, consider the following operation:
int value = 42;
int *ptr = &value;
int retrieved = *ptr;When *ptr is evaluated, the retrieval process occurs in
defined steps:
- Address Resolution: The runtime evaluates
ptrto get the raw numerical memory address it holds (the address ofvalue). - Byte Count Determination: Because
ptris declared as anint *, the compiler knows that a standard integer typically occupies 4 bytes on modern architectures. - Memory Fetch: The CPU issues a memory read request
starting at the address stored in
ptrand reads the next 4 consecutive bytes. - Type Interpretation: The retrieved 4-byte sequence
of bits is interpreted as a signed two's-complement integer and copied
into the destination variable
retrieved.
At the hardware level, dereferencing translates directly into
assembly load instructions using indirect addressing modes. On an x86-64
architecture, this is commonly handled by a mov instruction
(such as mov eax, [rdi]), where the brackets denote that
the CPU should fetch the contents stored at the address contained in the
register, rather than using the register's literal value.
Because dereferencing blindly reads memory based strictly on the
address provided, attempting to dereference an invalid, uninitialized,
or NULL pointer causes undefined behavior, often resulting
in a segmentation fault when the operating system blocks the illegal
memory access.