4.4. Dereferencing A Pointer: The Indirection Operator

Time: 00:04:45 | Download: Large, Large (CC), Small | Streaming, Streaming (CC) | Slides (PDF)

Directly accessing a "normal," non-pointer variable requires only one memory lookup or trip to memory. For example, using the variable i in the simple expression i + 5 requires accessing the memory location named by i once to load the value stored there. However, the dereference or indirection operator requires two memory accesses or lookups. The following illustration builds on the pointer operator examples from the previous section.

(a)
int	i;
int*	p;	// p is a pointer

i = 123;
p = &i;	// p stores the address of i
 
(b)
cout << *p << endl;
An animation highlighting the four steps taken to dereference p as outlined in (c).
Dereferencing a pointer variable.
  1. Statements from Figure 2 (a) and (b) in the previous section; p is a pointer variable that points to variable i
  2. In this context, the asterisk represents the dereference or indirection operator. The expression *p represents the value stored in variable i; so, the complete statement prints the value stored in i, not in p. We can view how the computer dereferences p as four consecutive steps. The computer:
    1. goes to the memory address represented by the variable name p,
    2. loads the value stored in p, which is the address of i (0x0a000010 in this example),
    3. goes to that memory location, and
    4. loads the value stored at that memory address (123 in this example).

The statement p = &i; makes a connection between the variables i and p. This connection makes it possible to access the value stored in i indirectly through p. That is, it is possible to use or change the value stored in i without using the variable name i! Figure 1 (b) demonstrates how to use the value stored in i indirectly through p, but the indirection operation may also appear on the left side of the assignment operator, making it possible to change the value of i without using variable name i: *p = 321;. Accessing i indirectly through p is called dereferencing p or more generally dereferencing a pointer.

Once the variables i and p are connected, the statement cout << i << " " << *p << endl; prints 123 123 (based on Figure 1 values). The first "123" comes directly from variable i, which only requires one trip to memory. The second "123" comes indirectly from variable i indirectly through p, which requires two trips to memory: one trip to get the address of i and the second trip to get the value stored in i. The following analogy describes the process in more familiar terms and might be easier to follow.

An illustration showing Tom's house with a note on the front door. An arrow labeled with the restaurant's address goes from Tom's house to the restaurant.
A dereference analogy. Tom and friends are meeting at a restaurant for dinner. The main group goes directly to the restaurant (one trip) and gets dinner. Dilbert is coming separately and doesn't know the restaurant's location but knows where Tom lives. Tom leaves a note with the restaurant's address on his front door. Dilbert first goes to Tom's house (first trip), where he finds the note. After getting the restaurant's address, Dilbert goes there (second trip), meets the group, and orders dinner. Maybe this situation happens frequently, but as long as Dilbert and Tom follow this same protocol, Dilbert always knows where to meet his friends. (Okay, this scenario was more likely in the days before cell phones and text messages, but work with me here.)
T data;
T* p = &data;
-----------------
T* p = new T;
A picture showing pointer p pointing to a block of data.
Summarizing the dereference operation. In the previous section, we illustrated the relation between a pointer and the data it points to by emphasizing that the relation involves two distinct locations in memory: the pointer and the data. The relation does not depend on the type of stored data, so you can replace "T" in the illustration with any data type. It's possible to directly access the value (i.e., the address) stored in the pointer just by using the name of the pointer variable: p. However, accessing the value stored in data is more complicated. In the first example (the code fragment above the line), we can access the data in two ways: directly by using the variable name data or indirectly through the pointer by using the dereference/indirection operator: *p. It's common for programs to define p and data in different scopes. In the second example (the code fragment below the line), we can only access the data indirectly through the pointer variable p.

Similarly, a program may create a pointer variable that can point to different data items at different times as the program executes. Alternatively, a program can define a single variable and access it from multiple, convenient locations within the program. Using a pointer, programmers can access the contents of a variable without using its name - they access the contents indirectly through the pointer.

Let's take a moment to review what we have just learned: We now understand the relation between a variable's name, its contents, and its address. We also know the three operators that define a pointer, find the address of a variable, and dereference a pointer. The following simple program demonstrates these operations.