多维数组与指针 精析

可以认为 C语言中只有一维数组,没有真正的二维数组。如二维数组 a[3][4]={{1,3,5,7},{9,11,13,15},{17,19,21,23}} ,

可以认为是一个 一维数组 : a[3]={ a[0], a[1], a[2] }其中 a[0],a[1],a[2] 又是三个有四个元素的一维数组,

   即 a[0]={ 1,3,5,7 },a[1]={ 9,11,13,15 }, a[2]={ 17,19,21,23 } 。

   现在大家考虑下面一个问题, 一维数 a[6]={1,2,3,4,5,6} 中, a 表示数组首地址,即 a[0] 地址, a+1 为 a[1] 地址,也即 a+1 指向 a[1], *(a+1) 是元素 a[1] 的值。

   对 二维数组 a[3][4] , a 是 数组首地址,但 a+1 不是 a[0][1] 的地址,而是与第 2 行,第 1 个元素 a[1][0] 的地址相等,也就是说 a+1 指向了下一行,若把 二维数组 a[3][4] 当作是由三个一维数组组成的数组(这三个一维数组的数组名分别为 a[0], a[1], a[2] ),则 a+1 指向了一维数组 a[1] 。而对 一维数组来说,数组名 a[0] 是元素 a[0][0] 的地址,所以 a[0]+1 是 a[0][1] 的地址,即 a+1 与 a[0]+1 都是地址,但指向的元素不一样, a+1 指向第二行的一维数组,而 a[0]+1 指向具体的数组元素 a[0][1] 。

  综合上述,总结如下:

   二维数组 a[3][4] , 可以看作是有三个以一维数组为元素的数组,这三个一维数组的数组名分别是 a[0], a[1] 和 a[2] 。

    数组名 a ,为数组首地址,即其第一个元素(一维数组)的地址,指向第一个元素(一维数组), a+1 指向第二个元素(第二个一维数组), a+2 指向 a[2]

又由于 a[0], a[1] 和 a[2] 为一 维数组,故它们也是数组的首地址。 a[0] 是第一个 一 维数组的数组名,即它是第 1 行第 1 个元素 a[0][0] 的地址,a[0]+1

指向 a[0][1], *(a[0]+1) 是 a[0][1] 的值。 也即,不管 二维数组还是 一维数组,它们的数组名都是数组的首地址,都指向数组的第一个元素,只不过,对二维数组

来说,数组名指向的是一个 一维数组(地址),而不是一具体数值;而对 一维数组来说,数组名指向的是一 具体数值,而不是一 个 地址。应特别注意的是 a,a[0]

都是地址,且数值是相同的,但 a 指向一维数组,而 a[0] 指向一个整型数值,它们的类型是不同的,所以 a+1 与 a[0]+1 的含义不但不同,数值也是不一样的。

  1. 多维数组的地址

   通过上面的讨论,我们直接得到以下结论:

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

 

 

 

a[0]

a[0]+1

 

 

a,a+0

1

3

5

7

a+1

9

11

13

15

a+2

17

19

21

23

 

   a 是 二维数组的名字,是二维数组的首地址,即第 0 行的首地址

   a+1 是数组 a 第 1 行首地址

   a[0],a[1],a[2] 是二维数组中三个一维数组的名字(地址),是第 0 行第 1 个 ,第 1 行第 1 个 ,第 2 行第 1 个元素 的首地址。

   a[i]+j 是第 i 行 j 列的地址

   *(a[i]+j) 是该地址存储的值,即 a[i][j]

   a+1 以行为单位移动,而 a[I]+1 在同一行以列(一个元素)为单位移动,所以 a+I 是行指针, a[I] 是列指针,a+1 是个指针,指向第一行的一维数组,那么

*(a+1) 就是个一维数组(的数组名),而第一行的一维数组的数组名是 a[1], 所以 *(a+1)=a[1], 也即 *(a+1) 指向了数组元素 a[1][0] ,变成了一个列指针,可

见对行指针进行 * 运算,就变成了列指针

  同理 a[1] 是数组名, &a[1] 表示指向该数组的一个指针,即 a+1, 可见对列指针(数组名)取地址,就得到一个行指针,也即指向一个一维数组的指针。

   大家思考一下 *(a+1)+1 和 *(*(a+1)+1) 的含义  /* (1)指向第一行第一列的指,(2)代表第一行

                                                 /*第一列指针所指的元素,前题都是从0行0列开始

   大家再思考一下 &a[1][0] 和 &(&a[1][0]) 的含义 /*(1)指第一行的列指针,(2)变成指向行的指针

   可以得到一个结论,对行指针进行一次 * 运算,它将变成列指针,进行两次 * 运算,它将变成一个数值

   同理,对数组元素进行一次 & 运算,它得到一个列指针,进行两次 & 运算,将得到一个行指针

  现在再来看以下式子的含义:

   a, *a, **a

   a+1, &a[1]

   a[1], *(a+1)

   a[1]+2, *(a+1)+2, &a[1][2]

   *(a[1]+2), *(*(a+1)+2), a[1][2]

  大家思考以下,下列式子值是否相同,含义是否也相同

   a, *a, a[0], &a[0][0]

   a+1, *(a+1), a[1], *(a[1])

   *(a[I]+j), *(*(a+I)+j), a[i][j]

 

  总结: 1. 二维数组名,指向一维数组的指针,行指针 三者等价

2. 一维数组名,指向具体元素的指针,列指针 三者等价

3. 行指针加 * ,变成列指针,行指针加 ** ,变成元素

4. 列指针加 * ,变成列元素,列指针加 & , 变成行指针

也即行指针、列指针、元素通过 [* , &] 两个运算符号,可以相互转化

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值