【时时三省】(C语言基础)通过指针引用数组元素2
山不在高,有仙则名。水不在深,有龙则灵。 ----CSDN 时时三省
要注意指针变量的当前值。
例题:
通过指针变量输出整型数组a的10个元素。
解题思路:
用指针变量p指向数组元素,通过改变指针变量的值,使p先后指向a [ 0 ] ~ a [ 9 ]各元素。
编写程序:
运行结果:
是一串乱码的 不是想要的结果
(在不同的环境中运行时显示的数据可能与上面的有所不同)。
程序分析:
显然输出的数值并不是a数组中各元素的值。需要检查和分析程序。有的人觉得上面的程序没有什么问题,即使已被告知此程序有问题,还是找不出问题出在哪里。问题出在指针变量p的指向。请仔细分析p的值的变化过程。指针变量p的初始值为a数组首元素(即a [ 0 ])的地址,经过第1个for循环读入数据后,p已指向a数组的末尾。因此,在执行第2个for循环时,p的起始值不是& a[0]了,而是a + 10。由于执行第2个for循环时,每次要执行p + +,因此p指向的是a数组P下面的10个存储单元,而这些存储单元中的值是不可预料的。
解决这个问题的办法是,只要在第2个for循环之前加一个赋值语句:p = a;使p的初始值重新等于& a [ 0 ]这样结果就对了。
程序为
( 1 )虽然定义数组时指定它包含10个元素,并用指针变量p指向某一数组元素,但是实际上指针变量p可以指向数组以后的存储单元。如果在程序中引用数组元素a [ 10 ],虽然并不存在这个元素(最后一个元素是a [ 9 ]),但C编译程序并不认为它非法。系统把它按* ( a + 10 )处理,即先找出( a + 10 )的值(是一个地址),然后找出它指向的单元( * ( a + 10 ) )的内容。这样做虽然在编译时不出错,但运行结果不是预期的,应避免出现这样的情况。这是程序逻辑上的错误,这种错误比较隐蔽,初学者往往难以发现。在使用指针变量指向数组元素时,应切实保证指向数组中有效的元素。
( 2 )指向数组元素的指针变量也可以带下标,如p [ i ]。有些读者可能想不通,因为只有数组才能带下标,表示数组某一元素。带下标的指针变量是什么含义呢?当指针变量指向数组元素时,指针变量可以带下标。因为在程序编译时,对下标的处理方法是转换为地址的,对p [ i ]处理成* ( p + i ),如果p是指向一个整型数组元素a [ 0 ],则p [ i ]代表a [ i ]。但是必须弄清楚p的当前值是什么?如果当前p指向a [ 3 ],则p [ 2 ]并不代表a [ 2 ],而是a [ 3 + 2 ],即a [ 5 ]。建议少用这种容易出错的用法。
( 3 )利用指针引用数组元素,比较方便灵活,有不少技巧。在专业人员中常喜欢用一些技巧,以使程序简洁。在看别人写的程序时可能会遇到一些容易使人混淆的情况,要仔细分析。
请分析下面几种情况(设p开始时指向数组a的首元素(即p = a)):
①分析:
p + +;
*p;
p++使p指向下一元素a [ 1 ]。然后若再执行*p,则得到下一个元素a[1]的值。
②* p + +;
由于+ +和*同优先级,结合方向为自右而左,因此它等价于* ( p++ )。先引用p的值,实现* p的运算,然后再使p自增1。
③* ( p++ )与* ( + + p )作用是否相同?不相同。前者是先取*p值,然后使p加1。后者是先使p加1,再取* p。若p初值为a(即& a[0] ),若输出*(p++),得到a [ 0 ]的值,而输出( + + p ),得到a [ 1 ]的值。
④+ + ( *p )。表示p所指向的元素值加1,如果p = a,则++( *p )相当于+ + a [ 0 ],若a[0]的值为3,则在执行+ + ( *p ) (即+ + a [ 0 ] )后a [ 0 ]的值为4。注意:是元素a [ 0 ]的值加1,而不是指针p的值加1。
⑤如果p当前指向a数组中第i个元素a [ i ],则:
* ( p--)相当于a [ i-- ],先对p进行“*”运算(求p所指向的元素的值),再使P自减。
* ( + + p )相当于a [ + + ],先使p自加,再进行“*”运算。
*(--p)相当于a[--i],先使p自减,再进行"*"运算
将++和--运算符用于指针变量十分有效,可以使指针变量自动向前或向后移动,指向下一个或上一个数组元素。