彻底理解C语言二维数组和指针

C语言二维数组以及用指针操作相对于一组数组而言有些复杂,这里尝试通过类比的方式快速理解。

首先我们要理解一组数组以及其指针操作方法。比如定义数组:int a[10],则a为数组第0个元素的地址,即:a ==&a[0];a+1表示 a[1]的地址,即a+1 == &a[1],依次类推有:a+i == &a[i]。等式两边同时进行取值操作,则有 *(a+i) == a[i]。即对于数组中的任一元素a[i],可以通过 *(a+i)来取得。这时我们如果再定一个指针:int *p = a,则p等效于a,也是数组第0个元素的地址,然后就可以用p来代替a操作,即:a[i] == *(p+i)。图示如下:

假如我们把几个一维数组放一起,如下图如示,有3个数组,数组名分别p0、p1、p2,没有任何问题。p0、p1、p2也分别代表三个数组的第0个元素的地址。这时我们再把p0、p1、p2放到一个数组中,数组名叫pp,也没有任何问题。这时二维数组就表示出来了:pp[3][4]。pp是二维数组的数组名,3表示里面有3个元素,每个元素都是一个地址,该地址是一个一维数组的第0个元素地址,4表示每个一维数组有4个元素。

跟一维数组一样,我们用二维数组的数组名对数组元素进行操作。假如我们要表示出下图中红色的那个元素即pp[1][2],首先要找出它所在的数组的首地址,为p1。所以pp[1][2] == *(p1+2)。而p1怎么得到呢?p1在数组pp中,先找到该数组的首地址pp,则p1==*(pp+1),把p1代进去,就有:pp[1][2] = *( *(pp+1) +2 )。对于任意元素,有pp[i][j] == *( *(pp + i) + j )。

我们再定义一个指针来代替数组名pp吧。怎么定义呢?能不能 int *p =pp呢?不行,因为 int *p中的p移动一次(即加1)是移动1个int字节,而从图中看出pp移动一次走4个int字节,所以类型不匹配,不能这样定义。怎么定义一次走4个int字节的指针呢?我们假设C语言作了这样的规定,就用:int (*p)[4]来表示。其中*p代表p是指针,int [4]代表类型。这样就可以有: int (*p)[4] = pp。推广开来,对一个二维数组type a[M][N],它的指针定义格式是:type (*p)[N] = a;其中任意元素a[i][j] == *( *(p + i ) + j)。

假如你认为 int (*p)[4]这个定义难以理解,非要用一个简单的指针来定义,这个指针为a[0][0](下图中蓝色元素)的地址,即:int *p = &pp[0][0],如下图所示。这时如何用指针p代表pp[1][2]即那个红色元素呢?关键还是要找到红色元素所在的数组首地址即p1。可以看出,p0移动4个位置(即一个数组的长度)就会到达下一个数组的首地址p1,即:p1 == p0 + 1*4,找到了首地址,就有:pp[1][2] == *(p1 + 2) ==  *( (p0 + 1 * 4) + 2);所以对于任意二维数组a[M][N],如果定义 *p = &&a[0][0],对于任意元素a[i][j],有:a[i][j] == *( a[i] + j) == *( ( p+ i * N) + j) 。

本文参考自:C语言二维数组指针表示

评论 8
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值