📄 ch08.htm
字号:
<P>Normal variables provide direct access to their own values. If you create a new
variable of type <TT>unsigned short int</TT> called <TT>yourAge</TT>, and you want
to assign the value in <TT>howOld</TT> to that new variable, you would write</P>
<PRE><FONT COLOR="#0066FF">unsigned short int yourAge;
yourAge = howOld;
</FONT></PRE>
<P>A pointer provides indirect access to the value of the variable whose address
it stores. To assign the value in <TT>howOld</TT> to the new variable <TT>yourAge</TT>
by way of the pointer <TT>pAge</TT>, you would write</P>
<PRE><FONT COLOR="#0066FF">unsigned short int yourAge;
yourAge = *pAge;
</FONT></PRE>
<P>The indirection operator (<TT>*</TT>) in front of the variable <TT>pAge</TT> means
"the value stored at." This assignment says, "Take the value stored
at the address in <TT>pAge</TT> and assign it to <TT>yourAge</TT>."
<BLOCKQUOTE>
<P>
<HR>
<FONT COLOR="#000077"><B>NOTE:</B></FONT><B> </B>The indirection operator (<TT>*</TT>)
is used in two distinct ways with pointers: declaration and dereference. When a pointer
is declared, the star indicates that it is a pointer, not a normal variable. For
example,</P>
<PRE><FONT COLOR="#0066FF">
unsigned short * pAge = 0; // make a pointer to an unsigned short</FONT></PRE>
</BLOCKQUOTE>
<PRE><FONT COLOR="#0066FF"></FONT></PRE>
<BLOCKQUOTE>
<P>When the pointer is dereferenced, the indirection operator indicates that the
value at the memory location stored in the pointer is to be accessed, rather than
the address itself.</P>
<PRE><FONT COLOR="#0066FF">*pAge = 5; // assign 5 to the value at pAge</FONT></PRE>
</BLOCKQUOTE>
<PRE><FONT COLOR="#0066FF"></FONT></PRE>
<BLOCKQUOTE>
<P>Also note that this same character (<TT>*</TT>) is used as the multiplication
operator. The compiler knows which operator to call, based on context.
<HR>
</BLOCKQUOTE>
<H4 ALIGN="CENTER"><A NAME="Heading11"></A><FONT COLOR="#000077">Pointers, Addresses,
and Variables</FONT></H4>
<P>It is important to distinguish between a pointer, the address that the pointer
holds, and the value at the address held by the pointer. This is the source of much
of the confusion about pointers.</P>
<P>Consider the following code fragment:</P>
<PRE><FONT COLOR="#0066FF">int theVariable = 5;
int * pPointer = &theVariable ;
</FONT></PRE>
<P><TT>theVariable</TT> is declared to be an integer variable initialized with the
value <TT>5</TT>. <TT>pPointer</TT> is declared to be a pointer to an integer; it
is initialized with the address of <TT>theVariable</TT>.<TT> pPointer</TT> is the
pointer. The address that <TT>pPointer</TT> holds is the address of <TT>theVariable</TT>.
The value at the address that <TT>pPointer</TT> holds is <TT>5</TT>. Figure 8.3 shows
a schematic representation of <TT>theVariable</TT> and <TT>pPointer</TT>.<BR>
<BR>
<A NAME="Heading12"></A><A HREF="figure3.jpg" tppabs="http://www.mcp.com/814147200/0-672/0-672-31070-8/art/ch08/figure3.jpg"><FONT COLOR="#000077">Figure
8.3.</FONT></A><FONT COLOR="#000077"> </FONT><I>A schematic representation of memory.</I>
<H4 ALIGN="CENTER"><A NAME="Heading13"></A><FONT COLOR="#000077">Manipulating Data
by Using Pointers</FONT></H4>
<P>Once a pointer is assigned the address of a variable, you can use that pointer
to access the data in that variable. Listing 8.2 demonstrates how the address of
a local variable is assigned to a pointer and how the pointer manipulates the values
in that variable.</P>
<P><A NAME="Heading14"></A><FONT SIZE="4" COLOR="#000077"><B>Listing 8.2. Manipulating
data by using pointers.</B></FONT></P>
<PRE><FONT COLOR="#0066FF">1: // Listing 8.2 Using pointers
2:
3: #include <iostream.h>
4:
5: typedef unsigned short int USHORT;
6: int main()
7: {
8: USHORT myAge; // a variable
9: USHORT * pAge = 0; // a pointer
10: myAge = 5;
11: cout << "myAge: " << myAge << "\n";
12:
13: pAge = &myAge; // assign address of myAge to pAge
14:
15: cout << "*pAge: " << *pAge << "\n\n";
16:
17: cout << "*pAge = 7\n";
18:
19: *pAge = 7; // sets myAge to 7
20:
21: cout << "*pAge: " << *pAge << "\n";
22: cout << "myAge: " << myAge << "\n\n";
23:
24:
25: cout << "myAge = 9\n";
26:
27: myAge = 9;
28:
29: cout << "myAge: " << myAge << "\n";
30: cout << "*pAge: " << *pAge << "\n";
31:
32: return 0;
<TT>33: }</TT></FONT>
<FONT COLOR="#0066FF">
Output: myAge: 5
*pAge: 5
*pAge = 7
*pAge: 7
myAge: 7
myAge = 9
myAge: 9
*pAge: 9
</FONT></PRE>
<P><FONT COLOR="#000077"><B>Analysis:</B></FONT><B> </B>This program declares two
variables: an <TT>unsigned short</TT>, <TT>myAge</TT>, and a pointer to an <TT>unsigned
short, pAge</TT>. <TT>myAge</TT> is assigned the value <TT>5</TT> on line 10; this
is verified by the printout in line 11.<BR>
On line 13, <TT>pAge</TT> is assigned the address of <TT>myAge</TT>. On line 15,
<TT>pAge</TT> is dereferenced and printed, showing that the value at the address
that <TT>pAge</TT> stores is the <TT>5</TT> stored in <TT>myAge</TT>. In line 17,
the value <TT>7</TT> is assigned to the variable at the address stored in <TT>pAge</TT>.
This sets <TT>myAge</TT> to <TT>7</TT>, and the printouts in lines 21-22 confirm
this.</P>
<P>In line 27, the value <TT>9</TT> is assigned to the variable <TT>myAge</TT>. This
value is obtained directly in line 29 and indirectly (by dereferencing <TT>pAge</TT>)
in line 30.
<H4 ALIGN="CENTER"><A NAME="Heading16"></A><FONT COLOR="#000077">Examining the Address</FONT></H4>
<P>Pointers enable you to manipulate addresses without ever knowing their real value.
After today, you'll take it on faith that when you assign the address of a variable
to a pointer, it really has the address of that variable as its value. But just this
once, why not check to make sure? Listing 8.3 illustrates this idea.</P>
<P><A NAME="Heading17"></A><FONT SIZE="4" COLOR="#000077"><B>Listing 8.3. Finding
out what is stored in pointers.</B></FONT></P>
<PRE><FONT COLOR="#0066FF">
1: // Listing 8.3 What is stored in a pointer.
2:
3: #include <iostream.h>
4:
5: typedef unsigned short int USHORT;
6: int main()
7: {
8: unsigned short int myAge = 5, yourAge = 10;
9: unsigned short int * pAge = &myAge; // a pointer
10:
11: cout << "myAge:\t" << myAge << "\tyourAge:\t" << yourAge << "\n";
12: cout << "&myAge:\t" << &myAge << "\t&yourAge:\t" << &yourAge <<"\n";
13:
14: cout << "pAge:\t" << pAge << "\n";
15: cout << "*pAge:\t" << *pAge << "\n";
16:
17: pAge = &yourAge; // reassign the pointer
18:
19: cout << "myAge:\t" << myAge << "\tyourAge:\t" << yourAge << "\n";
20: cout << "&myAge:\t" << &myAge << "\t&yourAge:\t" << &yourAge <<"\n";
21:
22: cout << "pAge:\t" << pAge << "\n";
23: cout << "*pAge:\t" << *pAge << "\n";
24:
25: cout << "&pAge:\t" << &pAge << "\n";
26: return 0;
<TT>27: }</TT>
Output: myAge: 5 yourAge: 10
&myAge: 0x355C &yourAge: 0x355E
pAge: 0x355C
*pAge: 5
myAge: 5 yourAge: 10
&myAge: 0x355C &yourAge: 0x355E
pAge: 0x355E
*pAge: 10
&pAge: 0x355A
</FONT></PRE>
<P>(Your output may look different.)</P>
<P><FONT COLOR="#000077"><B>Analysis:</B></FONT><B> </B>In line 8, <TT>myAge</TT>
and <TT>yourAge</TT> are declared to be variables of type <TT>unsigned short</TT>
integer. In line 9, <TT>pAge</TT> is declared to be a pointer to an <TT>unsigned
short</TT> integer, and it is initialized with the address of the variable <TT>myAge</TT>.<BR>
Lines 11 and 12 print the values and the addresses of <TT>myAge</TT> and <TT>yourAge</TT>.
Line 14 prints the contents of <TT>pAge</TT>, which is the address of <TT>myAge</TT>.
Line 15 prints the result of dereferencing <TT>pAge</TT>, which prints the value
at <TT>pAge</TT>--the value in <TT>myAge</TT>, or <TT>5</TT>.</P>
<P>This is the essence of pointers. Line 14 shows that <TT>pAge</TT> stores the address
of <TT>myAge</TT>, and line 15 shows how to get the value stored in <TT>myAge</TT>
by dereferencing the pointer <TT>pAge</TT>. Make sure that you understand this fully
before you go on. Study the code and look at the output.</P>
<P>In line 17, <TT>pAge</TT> is reassigned to point to the address of <TT>yourAge</TT>.
The values and addresses are printed again. The output shows that <TT>pAge</TT> now
has the address of the variable <TT>yourAge</TT> and that dereferencing obtains the
value in <TT>yourAge</TT>.</P>
<P>Line 25 prints the address of <TT>pAge</TT> itself. Like any variable, it has
an address, and that address can be stored in a pointer. (Assigning the address of
a pointer to another pointer will be discussed shortly.)
<BLOCKQUOTE>
<P>
<HR>
<B>DO</B> use the indirection operator (<TT>*</TT>) to access the data stored at
the address in a pointer. <B>DO</B> initialize all pointers either to a valid address
or to <TT>null</TT> (<TT>0</TT>)<B>. DO </B>remember the difference between the address
in a pointer and the value at that address.
<HR>
</BLOCKQUOTE>
<H3 ALIGN="CENTER"><A NAME="Heading19"></A><FONT COLOR="#000077">Pointers</FONT></H3>
<P>To declare a pointer, write the type of the variable or object whose address will
be stored in the pointer, followed by the pointer operator (<TT>*</TT>) and the name
of the pointer. For example,</P>
<PRE><FONT COLOR="#0066FF">unsigned short int * pPointer = 0;
</FONT></PRE>
<P>To assign or initialize a pointer, prepend the name of the variable whose address
is being assigned with the <TT>address of</TT> operator (<TT>&</TT>). For example,</P>
<PRE><FONT COLOR="#0066FF">unsigned short int theVariable = 5;
unsigned short int * pPointer = & theVariable;
</FONT></PRE>
<P>To dereference a pointer, prepend the pointer name with the dereference operator
(<TT>*</TT>). For example,</P>
<PRE><FONT COLOR="#0066FF">unsigned short int theValue = *pPointer
</FONT></PRE>
<H3 ALIGN="CENTER"><A NAME="Heading20"></A><FONT COLOR="#000077">Why Would You Use
Pointers?</FONT></H3>
<P>So far you've seen step-by-step details of assigning a variable's address to a
pointer. In practice, though, you would never do this. After all, why bother with
a pointer when you already have a variable with access to that value? The only reason
for this kind of pointer manipulation of an automatic variable is to demonstrate
how pointers work. Now that you are comfortable with the syntax of pointers, you
can put them to good use. Pointers are used, most often, for three tasks:
<UL>
<LI>Managing data on the free store.
<P>
<LI>Accessing class member data and functions.
<P>
<LI>Passing variables by reference to functions.
</UL>
<P>This rest of this chapter focuses on managing data on the free store and accessing
class member data and functions. Tomorrow you will learn about passing variables
by reference.
<H3 ALIGN="CENTER"><A NAME="Heading21"></A><FONT COLOR="#000077">The Stack and the
Free Store</FONT></H3>
<P>In the "Extra Credit" section following the discussion of functions
in Day 5, five areas of memory are mentioned:
<UL>
<LI>Global name space
<P>
<LI>The free store
<P>
<LI>Registers
<P>
<LI>Code space
<P>
<LI>The stack
</UL>
<P>Local variables are on the stack, along with function parameters. Code is in code
space, of course, and global variables are in global name space. The registers are
used for internal housekeeping functions, such as keeping track of the top of the
stack and the instruction pointer. Just about all remaining memory is given over
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -