📄 教学--第19章 指针一 基本概念.htm
字号:
<P>
<P>第二步、基于前一题,再加上一个指针变量,叫<SPAN lang=en-us> p2</SPAN>。
<P>
<P><SPAN lang=en-us>1) int k = 100;</SPAN>
<P><SPAN lang=en-us>2) int* p1 = &k;</SPAN>
<P><SPAN lang=en-us>3) int* p2 = p;</SPAN>
<P>
<P><SPAN lang=en-us>4) cout << *p1 << endl;</SPAN>
<P><SPAN lang=en-us>5) cout << *p2 << endl;</SPAN>
<P>
<P>编译并运行,观察结果应发现,<SPAN lang=en-us>*p </SPAN>和<SPAN lang=en-us> *p2
</SPAN>值相等,为什么?因为二者指向同一变量:k。
<P>
<P>第三步、请像第一步一样,观察,k 的地址,及p1, p2 的值。看三者是否相等。
<P>
<P>最后<SPAN lang=en-us>,</SPAN>将后面的两行输出删除,改为以下两行代码。第一行输出 k 的地址、p1、p2的值。
<P>第二行 输出k的值、*p1、*p2 值。
<P>
<P>//cout << *p1 << endl;
<P>//cout << *p2 << endl;
<P>
<P>cout << "&k = " << &k << ", p1 = " <<
p1 << ", p2 = " << p2 <<endl;
<P>cout << "k = " << k << ", *p1 = " << *p1
<< ", *p2 = " << *p2 <<endl; <BR>
<P>
<P>运行后结果如下:
<P align=center><IMG height=73 src="教学--第19章 指针一 基本概念.files/ls19.h5.jpg"
width=332 border=0>
<P align=center><SPAN lang=en-us>(1245064 </SPAN>是十进制的,它等于十六进制的<SPAN
lang=en-us> 0x0012FF88)</SPAN>
<P>
<H3><B><SPAN lang=en-us><A name=19.7>19.7</A>
</SPAN>上机实验二:改变指针所指变量的值,改变指针的指向</B></H3>
<P>
<P>尽管在上面的例子中修修改改也能改成本例,不过枝节太多的代码不会混淆了我们的目的。这次我们重点在于“改变”。
<P>
<P>第一步、 通过指针,改变其所指向的变量的值。(好绕啊!代码却很简单)
<P>
<P><SPAN lang=en-us>int k = 100;</SPAN>
<P>
<P><SPAN lang=en-us>int* p = &k;</SPAN>
<P>
<P><SPAN lang=en-us>//</SPAN>先输出一开始的k和*p的值<SPAN
lang=en-us>(</SPAN>用逗号分开<SPAN lang=en-us>)</SPAN>:
<P><SPAN lang=en-us>cout << k << "," << *p <<
endl; </SPAN>
<P>
<P><SPAN lang=en-us>//</SPAN>现在直接改变k值:
<P><SPAN lang=en-us>k = 200;</SPAN>
<P>
<P><SPAN lang=en-us>//</SPAN>输出此时的二者的值:
<P><SPAN lang=en-us>cout << k << "," << *p <<
endl; </SPAN>
<P>
<P><SPAN lang=en-us>//</SPAN>然后通过指针来改变k值:
<P><SPAN lang=en-us>*p = 300;</SPAN>
<P>
<P><SPAN lang=en-us>//</SPAN>输出此时的二者的值:
<P><SPAN lang=en-us>cout << k << "," << *p <<
endl; </SPAN>
<P>
<P><SPAN lang=en-us>system("PAUSE");</SPAN>
<P>
<P>输出将是:
<P>
<P align=center><IMG height=83 src="教学--第19章 指针一 基本概念.files/ls19.h6.gif"
width=159 border=0>
<P>
<P>可见,当p指向k以后,修改 *p 的值完全等同于直接修改 k值。
<P>
<P>第二步、改变指针的指向
<P>
<P>所谓的“改变指向”,其实就是“改变指针变量中存储的值(另一个变量的地址)”。我们一开始说的,两种不同的说法而已。
<P>在前面的代码最后,我们加上以下代码:
<P>
<P><SPAN lang=en-us>...</SPAN>
<P><SPAN lang=en-us>int m = 1000;</SPAN>
<P>
<P><SPAN lang=en-us>//</SPAN>现在p改为指向变量<SPAN lang=en-us> </SPAN>m<SPAN
lang=en-us> :</SPAN>
<P><SPAN lang=en-us>p = &m;</SPAN>
<P>
<P><SPAN lang=en-us> k = 400;</SPAN>
<P><SPAN lang=en-us>cout << k << "," << m << ","
<< *p << endl;<BR> </SPAN>
<P><SPAN lang=en-us>*p = 2000;</SPAN>
<P><SPAN lang=en-us>cout << k << "," << m << ","
<< *p << endl;</SPAN>
<P>
<P><SPAN lang=en-us>system("PAUSE");</SPAN>
<P>
<P>屏幕输出是:
<P align=center><IMG height=56 src="教学--第19章 指针一 基本概念.files/ls19.h7.gif"
width=158 border=0>
<P>
<P>当p改为指向m以后,之前指向的k便再也和它没有什么关系了。改变k值不会再影响p;而改变p值,则影响到m值而非k值。
<P>
<H3><B><SPAN lang=en-us><A name=19.8>19.8</A> </SPAN>指针的加减操作</B></H3>
<P>整型变量可以加减,求和,求差:
<P><SPAN lang=en-us>int a = 100;</SPAN>
<P><SPAN lang=en-us>int b = 99;</SPAN>
<P><SPAN lang=en-us>int c = a - b;</SPAN>
<P>
<P>而指针,由于它存的是一个内存地址,那么我们可以想到,对两个指针进行求和,求差,是没有意义的。想想,把你家的门牌号(206)和对面的的门牌号(207)相加(413),得到的数有什么意义吗?
<P>
<P>那么,指针的加减指什么呢?主要是指移动(而不是联通:()。比如,你家是206,那么,你的下一家,应该是206 + 1 =
207,而上一家则是206 - 1 =
205。你会说,我们这里的门牌号不是这样编的。但不管如何,大致应当是一个等差关系,或其它规律。都可以通过不断加上一个数,来得到下一家。
<P>
<H4><B><SPAN lang=en-us><A name=19.8.1>19.8.1</A> </SPAN>指向数组的指针</B></H4>
<P>
<P>现在,来说说指针指向一个数组的情况。
<P>
<P><SPAN lang=en-us>int arr[] = {1,2,3,4,5}; //</SPAN>一个数组
<P>
<P><SPAN lang=en-us>int* parr; //</SPAN>一个指针。
<P>
<P><SPAN lang=en-us>parr = arr; //</SPAN>没有<SPAN lang=en-us> </SPAN>‘<SPAN
lang=en-us>&</SPAN>’<SPAN lang=en-us> </SPAN>?对啊,对数组就是不用取址符。
<P>
<P><SPAN lang=en-us>cout << *parr << endl;
//</SPAN>输出<SPAN lang=en-us> *parr </SPAN>
<P>
<P>先猜想一下,输出结果是什么?
<P>
<P>最“直觉”的想法是:<SPAN lang=en-us>parr
</SPAN>指向一个数组,那么输出时,自然是输出数组中的所有元素了。所以答案应该是:“12345”了?
<P>不过,我想,学过前面的数组,我们就能知道这种想法错误。
<P>
<P>正确答案是输出数组中的第一个元素: 1 。
<P>
<P>接下来,如果是这样输出呢?
<P>
<P><SPAN lang=en-us>parr = arr;</SPAN>
<P><SPAN lang=en-us>cout << parr << endl;</SPAN>
<P>
<P>答案是输出了<SPAN lang=en-us>arr</SPAN>的地址。就等同于输出<SPAN lang=en-us> arr</SPAN>
。
<P><SPAN lang=en-us>cout << arr << endl;</SPAN> 的作用
<P>
<P>在这里,难点是要记住,数组变量本身就是地址。所以有:
<P>
<P>1、想让指针变量存储一个数组的地址(想让指针变量指向一个数组)时,不用取址符。
<P>2、解析一个指向数组的指针,得到的是数组的第一个元素。
<P>
<P>我们来看示意图:
<P>
<P align=center><IMG height=277 src="教学--第19章 指针一 基本概念.files/ls19.h9.gif"
width=452 border=0>
<P align=center>(指向数组的指针)
<P align=center>
<P>尽管数组中的每一个元素都有自已的地址,然而一个指向数组的指针,它仍然只是存储数组中第一个元素的地址。复习数组的章节,我们知道,数组中第一个元素的地址,就是数组的地址。即上图中的<SPAN
lang=en-us> 10000010</SPAN>。
<P>
<P>事实上,如果我们想故意让代码很难理解,则对于这一句:
<P>
<P><SPAN lang=en-us>parr = arr;</SPAN>
<P>可以改为:
<P><SPAN lang=en-us>parr = &arr[0];</SPAN>
<P>
<P>本来嘛, arr 和<SPAN lang=en-us> &arr[0]
</SPAN>的值就相等,我们在数组的章节已经学过。你若不信,可以输出一个:
<P><SPAN lang=en-us>cout << arr << "," << &arr[0]
<< endl;</SPAN>
<P>
<H4><B><SPAN lang=en-us><A name=19.8.2>19.8.2</A>
</SPAN>上机实验三:指向数组的指针</B></H4>
<P>
<P>int arr[2] = {1,2};
<P>int* p = &arr[0];
<P>
<P>//输出:指向数组的指针,数组的地址,数组中第一个元素的地址。
<P>cout << p << "," << arr << "," <<
&arr[0] << endl;
<P>
<P>system("PAUSE");
<P>
<P>结果是:
<P align=center><IMG height=34 src="教学--第19章 指针一 基本概念.files/ls19.h10.gif"
width=191 border=0>
<P align=center><SPAN lang=en-us>(</SPAN>指向数组的指针,数组的地址,数组中第一个元素的地址。<SPAN
lang=en-us>)</SPAN>
<P>
<H4><B><SPAN lang=en-us><A name=19.8.3>19.8.3</A> </SPAN>偏移指针</B></H4>
<P>
<P>请看前图的这一部分:
<P align=center><IMG height=66 src="教学--第19章 指针一 基本概念.files/ls19.h11.gif"
width=322 border=0>
<P align=center>
<P><SPAN lang=en-us>parr </SPAN>中存的值为 “10000010”。
<P>
<P>指针可以进行加减操作。假设我现在再定义一个指针:
<P>
<P><SPAN lang=en-us>int* parr2;</SPAN>
<P>
<P><SPAN lang=en-us>parr2 = parr + 1;</SPAN>
<P>
<P>现在问,<SPAN lang=en-us>parr2 </SPAN>的值是多少?有两种答案。一种说,<SPAN lang=en-us>
parr </SPAN>存的值是<SPAN lang=en-us> 10000010 </SPAN>,加1后,自然应为<SPAN
lang=en-us> 10000011</SPAN>了。这看似自然的答案又是错误了。
<P>
<P>正确答案:<SPAN lang=en-us>10000014</SPAN>。继续看前图另一小部分:
<P align=center><IMG height=111 src="教学--第19章 指针一 基本概念.files/ls19.h12.gif"
width=204 border=0>
<P align=center>(加1后,指针指向了下一个元素)
<P>
<P>加1后,指针指向了下一个元素。由于这是一个<SPAN lang=en-us> int
</SPAN>类型的数组,每个元素的大小是4个字节。所以第二个元素的地址是10000014。
<P>
<P><B>重点 <SPAN lang=en-us>& </SPAN>易错点:对指针
进行加1操作,得到的是下一个元素的地址,而不是原有地址值直接加1。</B>
<P>
<P>知到了如何“加”,也就知道了如何“减”。减以后,得到的是上一个元素的大小。
<P>
<P>所以,一个类型为 T 的指针的移动,以 <SPAN lang=en-us>sizeof(T) </SPAN>为移动单位。
<P>
<P>比如:<SPAN lang=en-us> </SPAN>
<P><SPAN lang=en-us>int* pInt; </SPAN>移动单位为 <SPAN lang=en-us>sizeof(int)
</SPAN>。即:4。而<SPAN lang=en-us> char* pChar; </SPAN>移动单位为<SPAN lang=en-us>
sizeof(char)</SPAN>。即1。
<P>
<P>试举一例:
<P>
<H4><B><SPAN lang=en-us><A name=19.8.4>19.8.4</A>
</SPAN>上机实验四:指针的最小移动单位</B></H4>
<P>
<P><SPAN lang=en-us>int arr[6] = {101,102,103,104,105,106};</SPAN>
<P><SPAN lang=en-us>int* pI = arr;</SPAN>
<P>
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -