CC++——⼆维数组与指针、指针数组、数组指针(⾏指针)、
⼆级指针的⽤法
1. ⼆维数组和指针
要⽤指针处理⼆维数组,⾸先要解决从存储的⾓度对⼆维数组的认识问题。我们知道,⼀个⼆维数组在计算机中存储时,是按照先⾏后列的顺序依次存储的,当把每⼀⾏看作⼀个整体,即视为⼀个⼤的数组元素时,这个存储的⼆维数组也就变成了⼀个⼀维数组了。⽽每个⼤数组元素对应⼆维数组的⼀⾏,我们就称之为⾏数组元素,显然每个⾏数组元素都是⼀个⼀维数组
下⾯我们讨论指针和⼆维数组元素的对应关系,清楚了⼆者之间的关系,就能⽤指针处理⼆维数组了。
设p是指向⼆维数组a[m][n]的指针变量,则有:
int* p=a[0];//此时P是指向⼀维数组的指针。P++后,p指向 a[0][1]。
如果定义int (*p1)[n];p1=a;p1++后,p1指向a[1][0];
则p+j将指向a[0]数组中的元素a[0][j]。
由于a[0]、a[1]┅a[M-1]等各个⾏数组依次连续存储,则对于a数组中的任⼀元素a[i][j],指针的⼀般形式如下:
p+i*N+j 相应的如果⽤p1来表⽰,则为*(p1+i)+j
元素a[i][j]相应的指针表⽰为:
*( p+i*N+j) 相应的如果⽤p1来表⽰,则为*(*(p1+i)+j)
同样,a[i][j]也可使⽤指针下标法表⽰,如下:
p[i*N+j]
例如,有如下定义:
int a[3][4]={{10,20,30,40,},{50,60,70,80},{90,91,92,93}};
则数组a有3个元素,分别为a[0]、a[1]、a[2]。⽽每个元素都是⼀个⼀维数组,各包含4个元素,如a[1]的4个元素是a[1][0]、a[1][1]、a[1]2]、a[1][3]。
若有:
int *p=a[0];
则数组a的元素a[1][2]对应的指针为:p+1*4+2
元素a[1][2]也就可以表⽰为:*( p+1*4+2)
⽤下标表⽰法,a[1][2]表⽰为:p[1*4+2]
特别说明:
对上述⼆维数组a,虽然a[0]、a都是数组⾸地址,但⼆者指向的对象不同,a[0]是⼀维数组的名字,它指向的是a[0]数组的⾸元素,对其进⾏“*”运算,得到的是⼀个数组元素值,即a[0]数组⾸元素值,因此,*a[0]与a[0][0]是同⼀个值;⽽a是⼀个⼆维数组的名字,它指向的是它所属元素的⾸元素,它的每⼀个元素都是⼀个⾏数组,因此,它的指针移动单位是“⾏”,所以a+i指向的是第i个⾏数组,即指向a[i]。对a进
⾏“*”运算,得到的是⼀维数组a[0]的⾸地址,即*a与a[0]是同⼀个值。当⽤int *p;定义指针p时,p的指向是⼀个int型数据,⽽不是⼀个地址,因此,⽤a[0]对p赋值是正确的,⽽⽤a对p赋值是错误的。这⼀点请读者务必注意。
2. ⽤⼆维数组名作地址表⽰数组元素。
另外,由上述说明,我们还可以得到⼆维数组元素的⼀种表⽰⽅法:
对于⼆维数组a,其a[0]数组由a指向,a[1]数组则由a+1指向,a[2]数组由a+2指向,以此类推。因此,*a与a[0]等价、*(a+1)与a[1]等价、* (a+2)与a[2]等价,┅,即对于a[i]数组,由*(a+i)指向。由此,对于数组元素a[i][j],⽤数组名a的表⽰形式为:
*(*(a+i)+j)
指向该元素的指针为:
*(a+i)+j
数组名虽然是数组的地址,但它和指向数组的指针变量不完全相同。
第⼀,指针变量的值可以改变,即它可以随时指向不同的数组或同类型变量,⽽数组名⾃它定义时起就确定下来,不能通过赋值的⽅式使该数组名指向另外⼀个数组。c语言二维数组表示方法
第⼆,数组名是指针,类型是指向元素类型的指针,但值是指针常量,声明数组时编译器会为声明所指定的元素数量保留内存空间。数组指针是指向数组的指针,声明指针变量时编译器只为指针本⾝保留内存空间。
例4 求⼆维数组元素的最⼤值。
该问题只需对数组元素遍历,即可求解。因此,可以通过顺序移动数组指针的⽅法实现。
main()
{
int a[3][4]={{3,17,8,11},{66,7,8,19},{12,88,7,16}};
int *p,max;
for(p=a[0],max=*p;p<a[0]+12;p++)
if(*p>max)
max=*p;
printf("MAX=%d/n",max);
}
执⾏结果:
MAX=88
这个程序的主要算法都是在for语句中实现的:p是⼀个int型指针变量;p=a[0]是置数组的⾸元素地址为指针初值;max=*p将数组的⾸元素值a[0][0]作为最⼤值初值;p<a[0]+12是将指针的变化范围限制在12个元素的位置内;p++使得每⽐较⼀个元素后,指针后移⼀个元素位置。例5 求⼆维数组元素的最⼤值,并确定最⼤值元素所在的⾏和列。
本例较之上例有更进⼀步的要求,需要在⽐较的过程中,把较⼤值元素的位置记录下来,显然仅⽤上述指针移动⽅法是不⾏的,需要使⽤能提供⾏列数据的指针表⽰⽅法。
main()
{
int a[3][4]={{3,17,8,11},{66,7,8,19},{12,88,7,16}};
int *p=a[0],max,i,j,row,col;
max=a[0][0];
row=col=0;
for(i=0;i<3;i++)
for(j=0;j<4;j++)
if(*(p+i*4+j)>max)
{
max=*(p+i*4+j);
row=i;
col=j;
}
printf("a[%d][%d]=%d/n",row,col,max);
}
程序运⾏结果:
a[2][1]=88
3. ⾏数组指针
在上⾯的说明中我们已经知道,⼆维数组名是指向⾏的,它不能对如下说明的指针变量p直接赋值:
int a[3][4]={{10,11,12,13},{20,21,22,23},{30,31,32,33}},*p;
其原因就是p与a的对象性质不同,或者说⼆者不是同⼀级指针。C语⾔可以通过定义⾏数组指针的⽅法,使得⼀个指针变量与⼆维数组名具有相同的性质。⾏数组指针的定义⽅法如下:
数据类型 (*指针变量名)[⼆维数组列数];
例如,对上述a数组,⾏数组指针定义如下:
int (*p)[4];
它表⽰,数组*p有4个int型元素,分别为(*p)[0]、(*p)[1]、(*p)[2]、(*p)[3] ,亦即p指向的是有4个int型元素的⼀维数组,即p为⾏指针
此时,可⽤如下⽅式对指针p赋值:
p=a;
4. 指针数组的定义
指针数组是指每个元素中存放的是指针。定义为 int *p[4];sizeof(p)=16,返回的是数组的总空间
5. ⼆级指针
⼆级指针:int**ptr:数据类型是int**,即指向指针的指针。
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论