⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 tut3-3.html

📁 a Complete C++ language tutorial on the cplusplus.com
💻 HTML
📖 第 1 页 / 共 2 页
字号:
<html>
<head>
<title>C++ Tutorial: 3.3, Pointers.</title>
<META NAME="description" CONTENT="Address and reference operators. Declaration, initialization and use of Pointers and arrays. Arithmetic of pointers. Pointers to pointers. void pointers. Pointers to functions.">
<META NAME="keywords" CONTENT="void indirection dereference ++ -- * & int*">
</head>

<body bgcolor="white">

<!--captut-->
<CENTER>
<TABLE WIDTH=100% CELLPADDING=0 CELLSPACING=1 BORDER=0>
<TR><TD WIDTH=90%>
 <FONT SIZE=4> Section 3.3 </FONT><BR>
 <FONT SIZE=5><B> Pointers </B></FONT>
</TD><TD><!--ad--><!--#include virtual="/ad/ad468.shtml"--><!--/ad-->
</TD><TD VALIGN="bottom"><A HREF="http://www.cplusplus.com/doc/tutorial/">
 <IMG SRC="head.gif" ALT="cplusplus.com" BORDER=0></A></TD></TR>
<TR><TD BGCOLOR="#0000FF" ALIGN="center" COLSPAN=3>
 <IMG SRC="head0.gif" WIDTH=2 HEIGHT=2 BORDER=0></TD></TR>
</TABLE>
</CENTER>
<!--/captut-->

<p>
We have already seen how variables are memory cells that we can access by an identifier.
But these variables are stored in concrete places of the computer memory.
For our programs, the computer memory is only a succession of 1 <I>byte</I> cells
(the minimum size for a datum), each one with a unique address.
<p>
A good simile for the computer memory can be a street in a city. On a street all houses
are consecutively numbered with an unique identifier so if we talk about 27th  
of Sesame Street we will be able to find that place without trouble,  since there must be
only one house with that number and, in addition, we know that the house will be between
houses 26 and 28.
<p>
In the same way in which houses in a street are numbered, the operating system
organizes the memory with unique and consecutive numbers, so if we talk about
location 1776 in the memory, we know that there is only one location with that address
and also that is between addresses 1775 and 1777.
<p>
<h2>Address (dereference) operator (<tt>&amp;</tt>).</h2>
At the moment in which we declare a variable it must be stored in a concrete
location in this succession of cells (the memory).  We generally do not decide where the
variable is to be placed - fortunately that is something automatically done by the compiler
and the operating system at runtime, but once the operating system has assigned an address
there are some cases in which we may be interested in knowing where the variable is stored.

<p>
This can be done by preceding the variable identifier by an <i>ampersand sign</i>
(<tt>&amp;</tt>), which literally means <i><b>"address of"</b></i>. For example:
<blockquote><tt>ted = &andy;</b></tt></blockquote>
would assign to variable <tt><b>ted</b></tt> the address of variable <tt><b>andy</b></tt>,
since when preceding the name of the variable <tt><b>andy</b></tt> with the
<i>ampersand</i> (<tt>&amp;</tt>) character we are no longer talking about the content
of the variable, but about its address in memory.
<p>
We are going to suppose that <tt><b>andy</b></tt> has been placed in the memory
address <tt><b>1776</b></tt> and that we write the following:
<blockquote><tt>
andy = 25;<br>
fred = andy;<br>
ted = &andy;
</tt></blockquote>
the result is shown in the following diagram:
<blockquote><img src="imgpoin1.gif"></blockquote>
We have assigned to <tt><b>fred</b></tt> the content of variable <tt><b>andy</b></tt>
as we have done in many other occasions in previous sections of this tutorial, but to
<tt><b>ted</b></tt> we have assigned <u>the address in memory</u> where the operating
system stores the value of <tt><b>andy</b></tt>, that we have imagined was
<tt><b>1776</b></tt> (it can be any address, I have just invented this one).
The reason is that in the allocation of <tt><b>ted</b></tt> we have
preceded <tt><b>andy</b></tt> with an <i>ampersand</i> (<tt>&amp;</tt>) character.
<p>
The variable that stores the address of another variable (like <tt><b>ted</b></tt>
in the previous example) is what we call a <b>pointer</b>.  In C++ pointers have
certain virtues and they are used very often. Farther ahead we will see how this type
of variable is declared.
<p>
<h2>Reference operator (<tt>*</tt>)</h2>

Using a pointer we can directly access the value stored in the variable pointed by it
just by preceding the pointer identifier with the reference operator
<i>asterisk</i> (<tt>*</tt>), that can be literally translated to
<i><b>"value pointed by"</b></i>. Therefore, following with the values of the previous example,
if we write:
<blockquote><tt>
beth = *ted;
</tt></blockquote>
(that we could read as:  "beth equal to <U>value pointed by</U> ted")
<tt><b>beth</b></tt> would take the value <tt><b>25</b></tt>, since
<tt><b>ted</b></tt> is
<tt><b>1776</b></tt>, and <i>the value pointed by</i> <tt><b>1776</b></tt>
is <tt><b>25</b></tt>.

<blockquote><img src="imgpoin2.gif"></blockquote>

You must clearly differenciate that <tt><b>ted</b></tt> stores <tt><b>1776</b></tt>,
but <tt><b>*ted</b></tt> (with an asterisk <tt>*</tt> before) refers to
the value stored in the address <TT><B>1776</B></TT>, that is <tt><b>25</b></tt>.
Notice the difference of including or not including the reference asterisk
(I have included an explanatory commentary of how each expression could be read):
<p>
<blockquote><tt><PRE>
<b>beth = ted;</b>   <FONT COLOR="green"><i>// beth equal to ted ( 1776 )</i></FONT>
<b>beth = *ted;</b>  <FONT COLOR="green"><i>// beth equal to <b>value pointed by</b> ted ( 25 )</i></FONT>
</pre></tt></blockquote>

<p><table cellpadding="5"><tr><td bgcolor="#BFBFFF">
<b>Operator of address or dereference (<tt>&amp;</tt>)</b><br>
It is used as a variable prefix and can be translated as <b>"address of"</b>, thus:
<tt> &amp;variable1</tt> can be read as <i>"address of <tt>variable1</tt>"</i>
<p>
<b>Operator of reference (<tt>*</tt>)</b><br>
It indicates that what has to be evaluated is the content pointed by the
expression considered as an address.  It can be translated by <b>"value pointed by"</b>.<br>
<tt>* mypointer</tt> can be read as <I>"value pointed by <tt>mypointer</tt>"</i>.
</td></tr></table>

<p>
At this point, and following with the same example initiated above where:<br>
<blockquote><tt>
 andy = 25;<br>
 ted = &andy;<br>
</tt></blockquote>

you should be able to clearly see that all the following expressions are true:
<BLOCKQUOTE>
<PRE><TT><FONT COLOR="blue">andy == 25
&andy == 1776
ted == 1776
*ted == 25</FONT></TT></PRE>
</BLOCKQUOTE>
The first expression is quite clear considering that its assignation was
<tt><b>andy=25;</b></tt>. The second one uses the address (or derefence) operator
(<tt>&amp;</tt>) that returns the address of the variable <tt><b>andy</b></tt>,
that we imagined to be <tt><b>1776</b></tt>. The third one is quite obvious since the second was true
and the assignation of <tt><b>ted</b></tt> was <tt><b>ted = &andy;</b></tt>.
The fourth expression uses the reference operator (<tt>*</tt>) that, as we have just seen,
is equivalent to the value contained in the address pointed by <tt><b>ted</b></tt>,
that is <tt><b>25</b></tt>.
<p>
So, after all that, you may also infer that while the address pointed by <TT><B>ted</B></TT>
remains unchanged the following expression will also be true:
<blockquote><tt><font color="blue">*ted == andy</font></tt></blockquote>

<p>
<h2>Declaring variables of type pointer</h2>
Due to the ability of a pointer to directly reference the value that it point to, 
it becomes necessary to specify which data type a pointer points to when declaring it.  
It is not the same to point to a <tt><b>char</b></tt> as it is to point to an <tt><b>int</b></tt> or a <tt><b>float</b></tt> type.
<p>
Therefore, the declaration of pointers follows this form:
<blockquote>
<tt><b><i>type * pointer_name</i>;</b></tt>
</blockquote>
where <tt><b><i>type</i></b></tt> is the type of data pointed, <u>not</u> the type of
the pointer itself.  For example:<br>
<blockquote><tt>
int * number;<br>
char * character;<br>
float * greatnumber;<br>
</tt></blockquote>
they are three declarations of pointers. Each one points to a different data type,
but the three are pointers and in fact the three occupy the same amount of space in memory
(the size of a pointer depends on the operating system), but the data to which they point
do not occupy the same amount of space nor are of the same type, one is <tt><b>int</b></tt>, another one is <tt><b>char</b></tt> and the other one <tt><b>float</b></tt>.
<p>
I emphasize that the asterisk (<tt>*</tt>) that we use when declaring
a pointer means only <i>that it is a pointer</i>, and should not be confused
with the reference operator that we have seen a bit earlier which is also written
with an asterisk (<tt>*</tt>). They are simply two different tasks represented with
the same sign.
<P><CENTER>
<TABLE WIDTH=100% CELLPADDING=5 CELLSPACING=5><TR><TD BGCOLOR="#FFFFBF" WIDTH=50% VALIGN="top">
<TT><PRE><I>// my first pointer</I>
#include &lt;iostream.h&gt;

int main ()
{
  int value1 = 5, value2 = 15;
  int * mypointer;

  mypointer = &value1;
  *mypointer = 10;
  mypointer = &value2;
  *mypointer = 20;
  cout &lt;&lt; "value1==" &lt;&lt; value1 &lt;&lt; "/ value2==" &lt;&lt; value2;
  return 0;
}
</PRE></TT>
</TD><TD BGCOLOR="silver" WIDTH=50% VALIGN="top">
<B><TT>value1==10 / value2==20</TT></B>
</TD></TR></TABLE>
</CENTER>
Notice how the values of <tt><b>value1</b></tt>
and <tt><b>value2</b></tt> have changed indirectly.  First we have assigned to
<tt><b>mypointer</b></tt> the address of
<tt><b>value1</b></tt> using the deference ampersand sign (<tt>&amp;</tt>). 
Then we have assigned
<tt><b>10</b></tt> to the value pointed by <tt><b>mypointer</b></tt>,
which is pointing to the address of <tt><b>value1</b></tt>, so
we have modified <TT><B>value1</B></TT> indirectly.

<p>
In order that you can see that a pointer may take several different values during the same
program we have repeated the process with <tt><b>value2</b></tt> and <u>the same</u>
pointer.
<p>
Here is an example a bit more complicated:

<TABLE WIDTH=100% CELLPADDING=5 CELLSPACING=5><TR><TD BGCOLOR="#FFFFBF" WIDTH=50% VALIGN="top">
<TT><PRE><I>// more pointers</I>
#include &lt;iostream.h&gt;

int main ()
{
  int value1 = 5, value2 = 15;
  int *p1, *p2;

  p1 = &value1;     <I>// p1 = address of value1</I>
  p2 = &value2;     <I>// p2 = address of value2</I>
  *p1 = 10;         <I>// value pointed by p1 = 10</I>
  *p2 = *p1;        <I>// value pointed by p2 = value pointed by p1</I>
  p1 = p2;          <I>// p1 = p2 (value of pointer copied)</I>
  *p1 = 20;         <I>// value pointed by p1 = 20</I>
  
  cout &lt;&lt; "value1==" &lt;&lt; value1 &lt;&lt; "/ value2==" &lt;&lt; value2;
  return 0;
}
</PRE></TT>
</TD><TD BGCOLOR="silver" WIDTH=50% VALIGN="top">
<B><TT>value1==10 / value2==20</TT></B>
</TD></TR></TABLE>
<P>
I have included as comments on each line how the code can be read:
ampersand (<tt>&amp;</tt>) as "address of" and asterisk (<tt>*</tt>)
as "value pointed by".  Notice that there are expressions with pointers
<tt><b>p1</b></tt> and <tt><b>p2</b></tt> with and without the asterisk.
The meaning of using or not using a reference asterisk is very different:
An asterisk (<tt>*</tt>) followed by the pointer refers to the place pointed by the
pointer, whereas a pointer without an asterisk (<tt>*</tt>) refers to the value of
the pointer itself, that is, the address of where it is pointing.
<p>
Another thing that can call your attention is the line:
<blockquote><tt>int *p1, *p2;</tt></blockquote>

that declares the two pointers of the previous example putting an asterisk (<tt>*</tt>)
for each pointer.  The reason is that the type for all the declarations of the same line
is <tt><b>int</b></tt> (and not <TT><B>int*</B></TT>). The explanation is because of the
level of precedence of the reference operator asterisk (<tt>*</tt>) that is the same as
the declaration of types, therefore, because they are associative operators from the
right, the asterisks are evaluated first than the type. We have talked about this
in <A HREF="tut1-3.html">section 1.3: Operators</A>, although it is enough that you know
clearly that -unless you include parenthesis- you will have to put an asterisk (<tt>*</tt>)
before each pointer that you declare.

<p>
<h2>Pointers and arrays</h2>
The concept of array is very much bound to the one of pointer. In fact, the identifier of an
array is equivalent to the address of its first element, like a pointer is equivalent to the
address of the first element that it points to, so in fact they are the same thing.
For example, supposing these two declarations:<br>
<blockquote><tt>
int numbers [20];<br>
int * p;<br>
</tt></blockquote>
the following allocation would be valid:
<blockquote><tt>
p = numbers;
</tt></blockquote>
At this point <tt><b>p</b></tt> and <tt><b>numbers</b></tt> are equivalent and they have
the same properties, the only difference is that 
we could assign another value to the pointer <tt><b>p</b></tt> whereas
<tt><b>numbers</b></tt> will always point to the first of the 20 integer numbers of
type <tt>int</tt> with which it was defined. So, unlike
<tt><b>p</b></tt>, that is an ordinary <i>variable pointer</i>,
<tt><b>numbers</b></tt> is a <i>constant pointer</i> (indeed an array name is a constant
pointer).
Therefore, although the previous expression was valid, the following allocation is not:
<blockquote><tt><font color="red">
numbers = p;<br>
</font></tt></blockquote>
because <TT><B>numbers</B></TT> is an array (constant pointer), and no values can be
assigned to constant identifiers.
<P>
Due to the character of <i>variables</i> all the expressions that include pointers
in the following example are perfectly valid:<br>

<P><CENTER>
<TABLE WIDTH=100% CELLPADDING=5 CELLSPACING=5><TR><TD BGCOLOR="#FFFFBF" WIDTH=50% VALIGN="top">
<TT><PRE><I>// more pointers</I>
#include &lt;iostream.h&gt;

int main ()
{

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -