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

📄 教学--第19章 指针一 基本概念.htm

📁 《白话c++网页版》是一本用浅显易懂的并具有点幽默的语调来讲述c++的高深的内容
💻 HTM
📖 第 1 页 / 共 4 页
字号:
          <TD width="6%" rowSpan=2>---<SPAN lang=en-us>&gt;</SPAN></TD>
          <TD width="23%" bgColor=#000000><FONT color=#ffffff>打开火折,但见</FONT>
            <P><FONT color=#ffffff>纸条内容:“XXX街3K号</FONT>”</P></TD>
          <TD width="6%" rowSpan=2>---<SPAN lang=en-us>&gt;</SPAN></TD>
          <TD width="15%" bgColor=#000000><FONT 
            color=#ffffff>你前往这纸条的神秘地址……</FONT></TD>
          <TD width="6%" rowSpan=2>---<SPAN lang=en-us>&gt;</SPAN></TD>
          <TD width="23%" bgColor=#000000><FONT 
            color=#ffffff>“XXX街3K号”里住着一千年老妖!你……</FONT></TD></TR>
        <TR>
          <TD width="21%">程序访问了一个没有初始化的指针:
            <P><SPAN lang=en-us>int* p;</SPAN></P></TD>
          <TD width="23%"><SPAN lang=en-us>p </SPAN>的内存是随机的一个数,比如:<SPAN 
            lang=en-us> 0x3FF0073D</SPAN></TD>
          <TD width="15%">程序随即访问内存地址:
            <P><SPAN lang=en-us>&nbsp;0x3FF0073D</SPAN></P></TD>
          <TD width="23%"><SPAN lang=en-us>0x3FF0073D</SPAN> 
            是哪里的内存?说不定正好是<SPAN lang=en-us>Windows</SPAN>老大要用的内存,你竟敢访问!
            <P><SPAN lang=en-us>Windows</SPAN>一生气,蓝屏。</P></TD></TR></TBODY></TABLE>
      <P>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 

      <P> 
      <P>既然没有赋值的指针这么危险,下面来看看如何给指针赋值。
      <P> 
      <H4><B><SPAN lang=en-us><A name=19.4.2>19.4.2</A> </SPAN>给指针变量赋值</B></H4>
      <P><SPAN lang=en-us></SPAN>&nbsp;
      <P><SPAN lang=en-us>(1)&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; int k = 
      100;</SPAN>
      <P><SPAN lang=en-us>(2)&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; int* 
      p;</SPAN>
      <P><SPAN lang=en-us>(3)&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; p = 
      &amp;k;</SPAN>&nbsp;&nbsp; //p取得变量<SPAN lang=en-us>k</SPAN>的地址 (也称:p指向k)
      <P> 
      <P>第1行定义一个整型变量k。
      <P>第2行定义了一个整型指针p。
      <P>而第3行,“指针 p 存储了变量k的地址”。短的说法是“<SPAN lang=en-us>p</SPAN>指向了<SPAN 
      lang=en-us>k</SPAN>”。
      <P> 
      <P>执行了上面三行代码后,结果是: p 指向 k。我们来看具体的内存示意图。
      <P> 
      <P align=center><IMG height=218 src="教学--第19章 指针一 基本概念.files/ls19.h1.gif" 
      width=273 border=0>
      <P align=center><SPAN lang=en-us>p </SPAN>指向 <SPAN lang=en-us>k </SPAN>示意图
      <P> 
      <P>上图中,红色数字代表什么?红数字11000002 是 变量 k 的内存地址。
      <P> 
      <P>指针初始化的结果,就是让它存储下另一个变量的地址。简称指向另一个变量。
      <P> 
      <P>下面说说三种常见的,给指针赋值的操作:
      <P> 
      <P><B>一、用<SPAN lang=en-us> &amp; </SPAN>取得普通变量的地址。</B>
      <P> 
      <P>要想让指针指向某个普通变量,需要通过<SPAN lang=en-us> &amp; </SPAN>来得到该普通变量的地址。
      <P> 
      <P><SPAN lang=en-us>int k;</SPAN>
      <P><SPAN lang=en-us>int* p = &amp;k;</SPAN>
      <P> 
      <P> 
      <P><B>二、指针之间的赋值。</B>
      <P>两个指针之间也可以相互赋值,此时不需要通过<SPAN lang=en-us> &amp; </SPAN>来取址。
      <P> 
      <P><SPAN lang=en-us>int k;</SPAN>
      <P> 
      <P><SPAN lang=en-us>int* p1</SPAN>
      <P><SPAN lang=en-us>int* p2;</SPAN>
      <P> 
      <P><SPAN lang=en-us>p1 = &amp;k;</SPAN>&nbsp; //<SPAN lang=en-us>p1 
      </SPAN>先指向<SPAN lang=en-us> k</SPAN>
      <P><SPAN lang=en-us>p2 = p1;&nbsp; //</SPAN>然后 ,p2 也指向<SPAN lang=en-us> 
      </SPAN>k。
      <P> 
      <P>注意,<SPAN lang=en-us>p2 = p1</SPAN>的结果是:让p2也指向“p1所指的内容”,而不是让p2指向“p1本身”。
      <P>上面的情况可以改为直接在定义时就赋值:
      <P><SPAN lang=en-us>int k;</SPAN>
      <P> 
      <P><SPAN lang=en-us>int* p1 = &amp;k;</SPAN>
      <P><SPAN lang=en-us>int* p2 = p1;</SPAN>
      <P> 
      <P><B>三、让指针指向数组</B>
      <P>数组本身就是地址,所以对数组变量也不用通过 <SPAN lang=en-us>&amp; </SPAN>来取址。
      <P> 
      <P><SPAN lang=en-us>char name[] = "NanYu";</SPAN>
      <P><SPAN lang=en-us>char* p = name;&nbsp; //</SPAN>不用取址符<SPAN lang=en-us> 
      &amp; </SPAN>
      <P> 
      <P>或者:
      <P> 
      <P><SPAN lang=en-us>int arr[3] = {100,99,80};</SPAN>
      <P><SPAN lang=en-us>int* p = arr;&nbsp; </SPAN>
      <P> 
      <P><B>四、让指针指向一个新地址</B>
      <P> 
      <P>前而的赋值方法都是让指针指向一个已有的内存空间的地址。比如:<SPAN lang=en-us>int* p = &amp;k</SPAN>; 
      指针变量<SPAN lang=en-us>p</SPAN> 
      存放的是已有的变量k的地址。其实指针也可以指向一个新开辟的内存空间,这一内存空间不归属于其它变量。
      <P> 
      <P>在C++中,常用一个关键字:<SPAN lang=en-us><B>new</B> </SPAN>来为指针开辟一段<B>新</B>空间。比如:
      <P> 
      <P><SPAN lang=en-us>int* p = <B>new</B> int;</SPAN>
      <P> 
      <P>现在,指针变量p存储着一个内存地址,该内存地址确实存在——它是由 <SPAN lang=en-us>new 
      </SPAN>操作符申请而得。可以这样认为,<SPAN lang=en-us>new 
      </SPAN>是一位特权人物,不通过它,指针只能指向已有的“房间”;而使用了它,则可以要求系统为指针“新开辟一片空地,然后建上新房间”。
      <P>有特权的人不仅仅是“new”,还有几个系统定义的函数,及<SPAN 
      lang=en-us>Windows</SPAN>提供的函数,都可以实现“向系统要空间”的功能。我们将在后面专门的 章节详细讲解。
      <P> 
      <H3><B><A name=19.5>1<SPAN lang=en-us>9</SPAN>.5</A> 地址解析 及其操作符<SPAN 
      lang=en-us> *</SPAN></B></H3>
      <P> 
      <P><SPAN lang=en-us>* 
      </SPAN>在C,C++语言里除了起“乘号”的作用以外,前面我们还刚学了它可以在定义变量时,表明某个变量是属于“指针类型”。现在,则要讲到它还能起“地址解析”的作用。
      <P> 
      <P>什么叫“地址解析”?假设有一<SPAN lang=en-us> int </SPAN>类型变量k:
      <P> 
      <P><SPAN lang=en-us>int k = 100;</SPAN>
      <P> 
      <DIV align=center>
      <CENTER>
      <TABLE id=AutoNumber2 
      style="BORDER-COLLAPSE: collapse; TEXT-ALIGN: center" borderColor=#111111 
      cellSpacing=0 cellPadding=0 width="49%" border=0>
        <TBODY>
        <TR>
          <TD width="39%">内存</TD>
          <TD width="61%">内存地址</TD></TR>
        <TR>
          <TD 
          style="BORDER-RIGHT: #000000 1px solid; BORDER-TOP: #000000 1px solid; BORDER-LEFT: #000000 1px solid; BORDER-BOTTOM: #000000 1px solid" 
          width="39%"><SPAN lang=en-us>100</SPAN></TD>
          <TD width="61%"><SPAN 
      lang=en-us>11000000</SPAN></TD></TR></TBODY></TABLE></CENTER></DIV>
      <P> 
      <P>方框是变量k所占用的内存。100 是该内存中存放的<B>值</B>。而<SPAN lang=en-us> 11000000</SPAN> 
      则是该内存的地址。
      <P> 
      <P>“地址解析”就是 <B>地址</B>-<SPAN lang=en-us>&gt;</SPAN><B>值</B> 的解释过程。即:通过地址 
      <SPAN lang=en-us>11000000 </SPAN>得到位于地址的变量。
      <P>可见“地址解析(*)” 和 “取址(<SPAN lang=en-us>&amp;</SPAN>)” 正好是一对相反的操作。
      <P> 
      <P>这好有一比:地址解析符 * 是个邮递员,他要根据信封上的地址,找到实际的房子。而 取址符 <SPAN lang=en-us>&amp; 
      </SPAN>则是当初到你家抄下门牌号的人。
      <P> 
      <P>看一下实际应用例子:
      <P> 
      <P><SPAN lang=en-us>int k = 100;</SPAN>
      <P><SPAN lang=en-us>int* p = &amp;k;</SPAN>
      <P><SPAN lang=en-us>int m = *p;</SPAN>
      <P> 
      <P><SPAN lang=en-us>cout &lt;&lt; m &lt;&lt; endl;</SPAN>
      <P> 
      <P>执行以上代码,屏幕上将输出 100。
      <P>实际上也可以这样写,以取得相同结果:
      <P> 
      <P><SPAN lang=en-us>int k = 100;</SPAN>
      <P><SPAN lang=en-us>int* p = &amp;k;</SPAN>
      <P> 
      <P><SPAN lang=en-us>cout &lt;&lt; *p &lt;&lt; endl;</SPAN>
      <P> 
      <P>直接输出<SPAN lang=en-us> *p </SPAN>即可。*p 的值就是<SPAN lang=en-us> 100.</SPAN>
      <P> 
      <P>明白了吗? <SPAN lang=en-us>p = &amp;k </SPAN>让p得到k的地址,而 *p 则得到k的值。
      <P>下面就考一考你<SPAN lang=en-us> &amp; </SPAN>和<SPAN lang=en-us> *</SPAN> 的作用。
      <P> 
      <P><SPAN lang=en-us>int k = 100;</SPAN>
      <P><SPAN lang=en-us>cout &lt;&lt; *&amp;k &lt;&lt; endl;</SPAN>
      <P> 
      <P>将会输出什么?
      <P> 
      <P>通过地址解析得到变量,不仅仅可以“得知”该变量的值,还可直接修改该变量的值。
      <P> 
      <P><SPAN lang=en-us>int k = 100;</SPAN>
      <P><SPAN lang=en-us>int* p = &amp;k; //p </SPAN>指向k
      <P> 
      <P><SPAN lang=en-us>*p = -100; </SPAN>
      <P><SPAN lang=en-us>cout &lt;&lt; k &lt;&lt; endl;</SPAN>
      <P> 
      <P>屏幕上将输出 -100。
      <P> 
      <H3><B><SPAN lang=en-us><A name=19.6>19.6</A> </SPAN>上机实验一 
      指向普通变量的指针和指针之间的互相赋值</B></H3>
      <P> 
      <P>实验一有多个步骤。
      <P> 
      <P>第一步、将上面的代码片段变成程序。请大家打开CB,新建空白控制台工程,然后输入以下代码。
      <P> 
      <P><SPAN lang=en-us>1) int k = 100;</SPAN>
      <P><SPAN lang=en-us>2) int* p1 = &amp;k;</SPAN>
      <P> 
      <P><SPAN lang=en-us>3) cout &lt;&lt; *p1 &lt;&lt; endl;</SPAN>
      <P> 
      <P><SPAN lang=en-us>4) system("PAUSE");</SPAN>
      <P> 
      <P><SPAN lang=en-us>(</SPAN>行前的编号是为下面讲课方便,你当然不能将它们输入到CB中去。<SPAN 
      lang=en-us>)</SPAN>
      <P> 
      <P>运行将查看结果。然后按任意键退出该程序。下面我们要亲眼看看,指针变量p1,是否真的存放着普通变量k的地址。
      <P> 
      <P>把断点设在第<SPAN lang=en-us>2</SPAN>行上。<SPAN 
      lang=en-us>(</SPAN>输入光标移到第二行,然后按F5<SPAN lang=en-us>)</SPAN>
      <P align=center><IMG height=35 src="教学--第19章 指针一 基本概念.files/ls19.h2.gif" 
      width=168 border=0>
      <P align=center>(设置断点)
      <P> 
      <P>按F9运行,程序停在断点上,然后按<SPAN lang=en-us> Ctrl + F7 </SPAN>调出<SPAN 
      lang=en-us>"Evaluate/Modify" 
      </SPAN>对话框。该对话框可以在程序运行时观察或强行修改某个变量的值。我们这里仅是想看看变量 k 的地址。所以如图输入 <SPAN 
      lang=en-us>&amp;k</SPAN> ,回车后,<SPAN 
      lang=en-us>Result</SPAN>(结果)栏出现:0012FF88。这就是k的地址。
      <P> 
      <P align=center><SPAN lang=en-us><IMG height=279 
      src="教学--第19章 指针一 基本概念.files/ls19.h2.jpg" width=402 border=0> </SPAN>
      <P align=center><SPAN lang=en-us>(&amp;k </SPAN>的值就是<SPAN lang=en-us> k 
      </SPAN>的内存地址<SPAN lang=en-us>)</SPAN>
      <P> 
      <P>接下来我们该看 p1 的值。看它是否等于<SPAN lang=en-us> 0012FF88</SPAN>。删除<SPAN 
      lang=en-us> &amp;k </SPAN>,改为<SPAN lang=en-us> 
      p</SPAN>1,回车,怎么回事?CB竟然很不配合地显示p1的值为 00000100 
      ?呵,这是因为当前断点那一行还没有运行呢,p1现在的值是随机的,这验证好我们前面说的“指向不明”。
      <P align=center><IMG height=78 src="教学--第19章 指针一 基本概念.files/ls19.h3.gif" 
      width=71 border=0>
      <P align=center><SPAN lang=en-us>(</SPAN>还没有初始化的指针p1,随随便便指向一个莫名的地址<SPAN 
      lang=en-us>)</SPAN>
      <P align=center> 
      <P>关掉该对话框,然后按F8再运行一步。再按<SPAN lang=en-us> Ctrl + F7 </SPAN>调出上面窗口,输入<SPAN 
      lang=en-us> p1,</SPAN>回车,这回显示的的值正合我们的推想。
      <P align=center><IMG height=132 src="教学--第19章 指针一 基本概念.files/ls19.h4.gif" 
      width=103 border=0>
      <P align=center>(p1 的值,就是<SPAN lang=en-us> k </SPAN>的地址,即:<SPAN 
      lang=en-us>p1 </SPAN>等于 <SPAN lang=en-us>&amp;k</SPAN>)
      <P> 

⌨️ 快捷键说明

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