Pointer Operators
The address operator (&) is a unary operator that returns the memory address of its operand. For example, assuming the declarations
int y = 5; // declare variable y int *yPtr; // declare pointer variable yPtr
the statement
yPtr = &y; // assign address of y to yPtr
assigns the address of the variable y to pointer variable yPtr. Then variable yPtr is said to "point to" y. Now, yPtr indirectly references variable y's value. Note that the use of the & in the preceding assignment statement is not the same as the use of the & in a reference variable declaration, which is always preceded by a data-type name.
Figure 8.2 shows a schematic representation of memory after the preceding assignment. The "pointing relationship" is indicated by drawing an arrow from the box that represents the pointer yPtr in memory to the box that represents the variable y in memory.
Figure 8.2. Graphical representation of a pointer pointing to a variable in memory.
Figure 8.3 shows another representation of the pointer in memory, assuming that integer variable y is stored at memory location 600000 and that pointer variable yPtr is stored at memory location 500000. The operand of the address operator must be an lvalue (i.e., something to which a value can be assigned, such as a variable name or a reference); the address operator cannot be applied to constants or to expressions that do not result in references.
Figure 8.3. Representation of y and yPtr in memory.
(This item is displayed on page 405 in the print version)
The * operator, commonly referred to as the indirection operator or dereferencing operator, returns a synonym (i.e., an alias or a nickname) for the object to which its pointer operand points. For example (referring again to Fig. 8.2), the statement
cout << *yPtr << endl;
prints the value of variable y, namely, 5, just as the statement
cout << y << endl;
would. Using * in this manner is called dereferencing a pointer. Note that a dereferenced pointer may also be used on the left side of an assignment statement, as in
*yPtr = 9;
which would assign 9 to y in Fig. 8.3. The dereferenced pointer may also be used to receive an input value as in
cin >> *yPtr;
which places the input value in y. The dereferenced pointer is an lvalue.
Common Programming Error 8.2
Dereferencing a pointer that has not been properly initialized or that has not been assigned to point to a specific location in memory could cause a fatal execution-time error, or it could accidentally modify important data and allow the program to run to completion, possibly with incorrect results. |
Common Programming Error 8.3
An attempt to dereference a variable that is not a pointer is a compilation error. |
Common Programming Error 8.4
Dereferencing a null pointer is normally a fatal execution-time error. |
The program in Fig. 8.4 demonstrates the & and * pointer operators. Memory locations are output by << in this example as hexadecimal (i.e., base-16) integers. (See Appendix D, Number Systems, for more information on hexadecimal integers.) Note that the hexadecimal memory addresses output by this program are compiler and operating-system dependent, so you may get different results when you run the program.
Figure 8.4. Pointer operators & and *.
(This item is displayed on page 406 in the print version)
1 // Fig. 8.4: fig08_04.cpp 2 // Using the & and * operators. 3 #include 4 using std::cout; 5 using std::endl; 6 7 int main() 8 { 9 int a; // a is an integer 10 int *aPtr; // aPtr is an int * -- pointer to an integer 11 12 a = 7; // assigned 7 to a 13 aPtr = &a; // assign the address of a to aPtr 14 15 cout << "The address of a is " << &a 16 << " The value of aPtr is " << aPtr; 17 cout << " The value of a is " << a 18 << " The value of *aPtr is " << *aPtr; 19 cout << " Showing that * and & are inverses of " 20 << "each other. &*aPtr = " << &*aPtr 21 << " *&aPtr = " << *&aPtr << endl; 22 return 0; // indicates successful termination 23 } // end main
|
Portability Tip 8.1
The format in which a pointer is output is compiler dependent. Some systems output pointer values as hexadecimal integers, while others use decimal integers. |
Notice that the address of a (line 15) and the value of aPtr (line 16) are identical in the output, confirming that the address of a is indeed assigned to the pointer variable aPtr. The & and * operators are inverses of one anotherwhen they are both applied consecutively to aPtr in either order, they "cancel one another out" and the same result (the value in aPtr) is printed.
Figure 8.5 lists the precedence and associativity of the operators introduced to this point. Note that the address operator (&) and the dereferencing operator (*) are unary operators on the third level of precedence in the chart.
Operators |
Associativity |
Type |
||||||
---|---|---|---|---|---|---|---|---|
() |
[] |
left to right |
highest |
|||||
++ |
-- |
static_cast<type>( operand ) |
left to right |
unary (postfix) |
||||
++ |
-- |
+ |
- |
! |
& |
* |
right to left |
unary (prefix) |
* |
/ |
% |
left to right |
multiplicative |
||||
+ |
- |
left to right |
additive |
|||||
<< |
>> |
left to right |
insertion/extraction |
|||||
< |
<= |
> |
>= |
left to right |
relational |
|||
== |
!= |
left to right |
equality |
|||||
&& |
left to right |
logical AND |
||||||
|| |
left to right |
logical OR |
||||||
?: |
right to left |
conditional |
||||||
= |
+= |
-= |
*= |
/= |
%= |
right to left |
assignment |
|
, |
left to right |
comma |