1.引用一个数组元素有两种方法:
(1)下标法,如a[i]的形式;
(2)指针法,如*(a+i)
或*(p+i)
。其中a是数组名,p是指向数组元素的指针变量,其初值p=a。
【注意】
在使用指针变量指向数组元素时,要注意以下问题:
(1)可以通过改变指针变量的值指向不同的元素。例如,当用指针变量p指向数组中的某一元素,用p++使p的值不断改变从而指向不同的元素。
如果不用p变化的方法而用数组名a变化的方法(例如,用a++)是不行的。因为数组名a代表数组首元素的地址,它是一个指针型常量,所以a++是无法实现的。
(2)要注意指针变量的当前值。具体看下面的例子。
【例】通过指针变量输出整型数组a的10个元素。
【解题思路】用指针变量p指向数组元素,通过改变指针变量的值,使p先后指向a[0]~a[9]各元素。
【程序代码】
int main(){int a[10];int* p = a;printf("输入10个数字:");for (int i = 0; i < 10; i++)scanf("%d", p++);for (int i = 0; i < 10; i++, p++)printf("%d ", *p);return 0;}
【运行结果】
【结果分析】
(1)输出的数值并不是a数组中各元素的值。
(2)造成这个结果的原因是指针变量p的指向有问题。
指针变量p的初始值为a数组首元素的地址,经过第一个for循环读入数据之后,p已指向该数组的末尾。因此在执行第二个for循环时,p的起始值就不是&a[0]了,而是a+10。由于执行第二个for循环时,每次都要执行p++,因此p指向的是a数组下面的10个存储单元,而这些存储单元的值是不可预测的。如下图所示:
【改正以上代码】
解决办法:在第二个for循环之前加上一个赋值语句:p=a;
,使p的初始值重新等于&a[0],这样结果就对了,代码如下:
int main(){int a[10];int* p = a;printf("输入10个数字:");for (int i = 0; i < 10; i++)scanf("%d", p++);p = a;for (int i = 0; i < 10; i++, p++)printf("%d ", *p);return 0;}
【运行结果】
总结
1.从上例可以看出,虽然定义数组时指定它包含10个元素,,并用指针变量p指向某一数组元素,但是**实际上指针变量p可以指向数组以后的存储单元。**如果在上例的程序中我们引用数组元素a[10],虽然并不存在这个元素,但是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))。
(1)分析:
p++;*p;
p++使p指向下一元素a[1]。然后若再执行*p,则得到下一个元素a[1]的值。
(2)*p++;
由于++和*
同优先级,结合方向为自右向左,因此*p++;
等价于*(p++);
。先引用p的值,实现*p
的运算,然后再使p自增1。
上例程序中的第二个for语句
for (int i=0;i<10;i++,p++)printf("%d ",*p);
可以改写为
for(int i=0;i<10;i++)printf("%d ",*p++);
作用完全一样。它们的作用都是先输出*p的值,然后使p值加1,这样下一次循环时,p就是下一个元素的值。
(3)*(p++)
与*(++p)
作用不相同。
*(p++)
是先取*p
的值,然后使p+1。
*(++p)
是先使p+1,再取p。
若p初值为a(即&a[0]),若输出*(p++)
,得到a[0]的值,而输出*(++p)
,得到a[1]的值。
(4)++(*p)
表示p所指向的元素值加1,如果p=a,则++(*p)
相当于++a[0]
,若a[0]的值为3,则执行++(*p)
(即++a[0]
)之后,a[0]的值为4。注意:是元素a[0]的值加1,而不是指针p的值加1。
(5)如果p当前指向a数组中第i个元素a[i],则:
①*(p--)
相当于a[i--]
,先对p进行*
运算(求p所指向的元素的值),再使p自减。
②*(++p)
相当于a[++i]
,先使p自加,再进行*
运算。
③*(--p)
相当于a[--i]
,先使p自减,再进行*
运算。
【注意】
在用*p++
形式的运算时,一定要十分小心,弄清楚先对p进行*
运算还是先使p自增或自减。