c语言数组的作用范围,C语言中多维数组指针的“级别”

在学习C语言的过程中,多维数组的指针是一个难点,许多初学者接受起来都感到困难,特别是对二维数组中a+i=a[i]=*(a+i)这样的等式不能理解,而在应用中对“行指针”和变量指针的运用也经常出现错误。纠其原因,主要是没有抓住问题的关键,同时又受到一维数组思维惯性的影响,不能从较高的角度来掌握问题的本质。笔者总结多年讲授C语言的教学经验,提出用“级别论”的方法来分析问题,收到了较好的效果,能够帮助初学者加深对这一问题的理解。

1 数组地址的“级别”1.1 什么是数组地址的“级别”?

为了有助于对问题的理解,我们人为地给数组的地址“定级”,以二维数组为例,已知有如下说明语句:

static int a[3][4];

则a+i、a[i]、&a[i][0]都表示地址,且有a=a[i]=&a[i][0],它们的区别是什么?我们说,a是“二级地址”,它是指向“行”的;a[i]是“一级地址”,它是指向元素的。归纳起来我们有如下论断:

二维数组名+i=“二级地址”,它指向数组中的某一行,称为“行地址”;

一维数组名+i=“一级地址”,它指向数组中的某一个元素,称为“元素地址”或“点地址”;

作为特例,我们可以把数组元素称为“0级地址”。

1.2 各级地址的取值范围

二级地址的取值范围是各行的首地址,亦即每一行第一个元素的地址,因此有a+i=&a[i][0];而一级地址的取值范围是所有元素地址值,因此有a[i]+j=&a[i][j]。由此可以看出,一、二级地址的值域有相交的部分。当一、二级地址都取某一行的首地址时,它们的值便相等了。此时便有:

a+i=a[i]=*(a+i)=&a[i][0]。

1.3 推广到一般情况

对于三维数组,我们有:

三维数组名+i=“三级地址”,它指向数组中的某一平面,称为“层地址”;

二维数组名+i=“二级地址”,它指向数组中的某一直线,称为“行地址”;

一维数组名+i=“一级地址”,它指向数组中的某一个元素,称为“点地址”。

例如int

a[3][4][5];是一个三维数组,则a表示三级地址,a[0]表示二级地址,a[0][0]表示一级地址,而a[0][0][0]则表示元素(0级地址)。

用此方法,我们可以推广到n维数组,n维数组中的最高级地址是“n级地址”。当然超过三维时,我们便难以给出它的几何解释。2 运算符*与[]的作用在表示多维数组的指针时,数组名与指针运算符*和下标运算符[]紧密的结合在一起,此时两者的作用是等价的,它们都起到“降级”的作用。若a表示二级地址,则a[0]和*a表示一级地址,a[0][0]和**a则表示元素。由此可以看出,每增加一个*或[],地址的级别就下降一级,在这里*和[]可以混合使用,例如*(a[i]+j

),*(*(a+i)+j),

a[i][j]都表示二维数组中第i行第j列的元素。判断一个指针常量或变量的“级别”只需查看表达式中*与[]的个数便一目了然了。3 指针变量的“级别”与指针常量(地址)相对应指针变量也有它的“级别”。指针变量的级别是由其定义方式决定的。

3.1 设p为指针变量,若其定义语句为int

(*p)[n]则p为二级指针变量,它的初值也只能是二级地址,此时p+1指向下一行,亦即“二级指针按行移动”。

例1、输出二维数组任一行任一列元素的值

main ()

{ static int

a[3][4]={1,3,5,7,9,11,13,15,17,19,21,23};

int i,j,(*p)[4];/* 定义二级“行指针”p */

p=a; /*二级指针变量的初值为二级地址 */

scanf (″i=%d, j=%d ″, &i, &j);

printf (″a[%d, %d]=%d\n ″,i,j,*(p+i)+j));

}

运行结果:

i=1, j=2

a[1,2]=13

3.2 设p为指针变量,若其定义语句为 int

*p;则p为一级指针变量,它的初值也只能是一级指针,此时p+1指向“下一个元素”,亦即一级指针按元素移动。

例2、用指针变量输出数组元素的值。

main ()

{ static int

a[3][4]={1,3,5,7,9,11,13,15,17,19,21,23};

int i, (*p) /* 定义一级p */

p=a[0]; /*一级指针变量的初值只能是一级地址 */

for (p=a[0]; p

{if ((p-a[0])%4==0) printf (″\n ″)

printf (″%4d ″, *p);

}

}

运行结果:

1  3  5  7

9  11 13 15

17 19 21 23

虽然在二维数组中a=a[0]=&a[0][0],但在例1中对指针变量赋值的语句只能写成p=a;而不能写成p=a[0]或p=&a[0][0];而在例2中,由于a[0]或&a[0][0]都是一级地址,所以p=a[0]可以代换成p=&a[0][0]。

3.3 设p为指针变量,若其定义语句为 int

(*p)[n][m]则p为三级指针变量,它的初值是三级指针,此时p+1指向下一层,亦即三级指针按层移动。

例3、输出三维数组某一行某一列元素的下标值

main ()

{static int a[2][3][4]

={1,3,5,7,

9,11,13,15,

17,19,21,23,

25,27,29,31,

33,35,37,39,

41,43,45,47};

int i,j,k,m;

int (*p) [3][4];/* 定义一个三维的层指针 */

p=a; /* 把三级地址赋给三级指针变量 */

printf (″a[i][j][k]= ″);

scanf (″%d ″, &m);

for (i=0; i<2; i++)

for (j=0; j<3; j++)

for (k=0; k<4; k++)

if(*(*(*(p+i)+j)+k)==m)

printf (″i=%d, j=%d, k=%d\n ″, i+1,j+1,k+1);

}

运行结果:

a[i][j][k]=45

i=2,j=3,k=3

例1、例2为谭浩强编C程序设计教材中的例题,例3为自编例题。

所有程序在PC486/DX66、Turbo C 2.0环境下调试通过。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值