5.3.1 指针与一维数组
前面讨论数组时,对数组元素的访问是采用的下标法,即是以数组的下标确定数组元素的。在引入指针变量后,我们可以利用一个指向数组的指针来完成对数组元素的存取操作及其他运算,这种方法称为指针法。在C语言中,指针和数组之间存在密切的联系。一个数组名实际上是一个指针常量,它的值是指向这个数组的第一个元素的起始地址。在定义数组时,编译程序就将该地址赋予了数组名。数组名就是数组起始地址的符号地址。
当在程序中定义一个数组时,例如:
int data[10];
C编译程序为该数组分配了10个整型数据所需要的连续的存储空间,依次存放其10个数组元素data[0]~data[9]并将存储空间的首地址赋予数组名data。由于在程序运算过程中,给数组data所分配的存储空间不会改变,因此data即为存放数组起始地址的指针常量,即
data 与 &data[0]等效
data+i 与 &data[i]等效
若定义一个指针变量p及数组data:
int*p,data[10];
执行赋地址操作:
p=data; 或 p=&data[0];
则将指针p指向数组data的第一个元素,如图5.3.1所示。由于表达式p+i表示的地址值与&data[i]表示的地址值相同,因此可以通过表达式中i值的变化(i=0,1,2,…,9)来实现对数组data中各元素的访问。
图5.3.1 指针与数组元素之间的关系
注意:当指针变量一旦指向一维数组的起始地址,指针变量名可以当成一维数组名使用,因此data[i]与p[i]是等效的,即有:
如图5.3.1所示,以下赋值语句等效:
*p=100; 等效于 data[0]=100;
*(p+1)=200; 等效于 data[1]=200;
*(p+i)=500; 等效于 data[i]=500;
若指针p当前指向数组的起始地址,执行语句:
p=p+4
则将指针从指向数组的第一个元素改变为指向数组的第五个元素data[4],此时:
*p 表示 data[4]
*(p+1) 表示 data[5]
*(p−1) 表示 data[3]
因此,对数组元素的访问可用下标方式,也可以用指针方式,通常下标方式适于随机访问数组。在C语言中,用指针自增、自减的操作可实现对数组的快速顺序访问,提高程序的运行效率。
应该注意:虽然数组名data和指针p中均存放的是地址值,但data是一个指针常量,其值是由编译程序给定的数组起始地址,是不能改变的,而指针p是一个指针变量,它可以指向任一个数组元素。因此,以下语句是合法的:
p=data;
p++;
p=p+3;
但以下语句是非法的:
data=p; /*不能改变数组data的起始地址*/
data++;
data=data+3;
例5-5 指针与数组的关系。
程序如下:
程序运行结果:
输出结果表明:表达式*(p+i)和data[i]是等价的,是用指针法和下标法来表示访问数组元素的两种不同形式。
例5-6 使用指针计算fibonacci数列的前15个数。
程序如下:
输出结果:
0 1 1 2 3 5 8 13 21 34 55 89 144 233 377
指针可访问一维数组,也可访问多维数组。以二维数组为例,指向二维数组的指针的概念和使用方法比指向一维数组的指针要复杂一些。
一个二维数组,实际上可以看成由若干个按行主序存放的一维数组构成的,例如有定义:
int a[5][4];*pa;
二维数组a,共包括20个整型数据,可看成由a[0]~a[4] 5个一维数组元素构成,而每个数组元素又是一个由4个数组元素构成的一维数组(如图5.3.2所示)。
图5.3.2 二维数组的构成
根据二维数组由一维数组构成的组织结构及二维数组按行主序顺序连续存放的存储结构不难将指向一维数组的指针推广到指向二维数组的指针,如上所定义的整型指针pa。
pa=a[0];表示将一维数组a[0]的起始地址赋给指针pa,即pa指向一维数组a[0]的第一个元素a[0][0]。
与该赋值语句等效的语句有:
pa=a; 或 pa=&a[0][0];
而语句:
pa++;表示pa自增1,即将指针pa指向元素a[0][1]。
同理,若执行
pa=a[4];表示将一维数组a[4]的地址赋给指针pa,也即将指针指向数组元素a[4][0]。
*pa 即为数组元素a[4][0]的值。
例5-7 用指针变量输出数组元素的值。
程序如下:
程序运行结果:
免责声明:以上内容源自网络,版权归原作者所有,如有侵犯您的原创版权请告知,我们将尽快删除相关内容。