本节书摘来自异步社区《指针的编程艺术(第二版)》一书中的第3章,第3.2节,作者 蔡明志,更多章节内容可以访问云栖社区“异步社区”公众号查看
指针的编程艺术(第二版)
一维数组与指针的关系前面已经介绍过。一维数组的元素值,可使用[]或一个*得到,假设有一个数组如下:
则(i+2) 或i[2] 或(ptr+2) 或ptr[2],都表示数组某一个元素的值。而二维数组(two dimension array){xe "二維陣列(two dimension)"},则需要两个,或一个与一个[ ],或两个[ ],才能得到数组的元素值。其余的表示法,只能得到数组元素的地址。
假设一个二维数组的定义如下,

其中j是此数组的名称,表示这个数组第1行第1列元素的地址,而j+1是第2行第1列元素的地址,除此之外
j[0]和j[1]等同于j和j+1,表示第1行第1个元素和第2行第1个元素的地址。j和j[0] 虽然表示同一元素的地址,但两者对于加1个单位的意思不同。
j+1表示第2行第1个元素的地址,也即是j+1==&j1。而j[0]+1是第1行第2个元素的地址,也就是j[0]+1==&j0,如下图所示。
关于二维数组的每个元素所在内存的概念已在第1章讨论过,请参阅范例address2array-5和address2array-10。
接下来,请问j和(j+1)是某个元素的地址,还是某个元素的值呢?答案是某个元素的地址。j与j都表示第1行第1列元素的地址(&j0)。而j+1与(j+1) 都表示第2行第1列元素的地址(&j1),如下图所示。
虽然j与j表示相同的意思,但两者都加1,表示的意义是不相同的。j+1表示第2行第1列的地址,而 j+1表示第1行第2列元素的地址(&j0)。同理,*(j+1)+1是第2行第1列的元素地址(&j1)。请参阅范例pointerarr2-5。
范例pointerarr2-5
输出结果
从输出结果可知,每列之间相距8个字节,因为每列有两个int的元素。
综上所述,如果有一个二维数组k,如下所示:
数组的示意图如下图所示。
如何得到元素值6(位于第2行第3个元素)的地址呢?答案如下:
从&k1可以很清楚地看出,它表示k1元素的地址。*(k+1)和k[1]都表示第2行第1个元素的地址,所以再加2,都可得到第2行第3个元素的地址。
当我们得到元素的地址后,再加上一个*就可以得到该元素的值,所以
都可以得到数组第2行第3列的值。由以上的语句,可以推导出以下的公式。
这一公式很容易理解,因为*和[]是互通的。请参阅范例pointerarr2-10。
范例pointerarr2-10
范例程序使用3种方法,得到k1 的地址与数值。要得到k1 的值6,可以使用(k[1]+2)及((k+1)+2)。如果要得到k1 的地址,则可使用&k1、k[1]+2及(k+1)+2,此处以%p输出数组第2行第3个元素的地址是0022ff58。如果使用%x取代%p,则会省略前面的0。两者都可以用于输出内存地址。