二维数组仅仅是一个逻辑上的概念,在实际的存储中,由于内存本身是一维的,因此在C语言中是按照“行”的顺序进行存储的,即依次存放数组的每一行。从存储形式上看,二维数组的存储形式仍然是一维的。如有二维数组int arr[4][3],则其逻辑结构及存储结构如图7-10所示。
图7-10 二维数组逻辑结构及存储结构
由图7-10可知,二维数组arr[4][3]从存储上来说,可以看成是一个包含了arr[0]、arr[1]、arr[2]和arr[3]共4个单元的一维数组,只不过每一个单元中存储的又是一个长度为3的一维数组,其下标分别为0、1和2。arr[i]就是数组arr的第i个单元,同时又可以看成是第i个单元中的一维数组的名字,在引用数组arr中的某一个单元时可以分成两步来引用。以引用arr[2][1]为例,首先对于一维数组arr来说,引用的是它的第二个单元,可以写成arr[2],由于arr[2]单元中存放的又是一个一维数组,此时将arr[2]看成此一维数组的名字,要使用的是它的1号单元,因此用数组名加下标的引用形式,就是arr[2][1],这也就是大家所熟知的二维数组元素的下标引用。
2.二维数组中的地址表示
在学习二维数组中的单元地址表示方法以前,请大家先看一个例子。
请大家思考,该程序能正确执行吗?答案是否定的,请大家上机验证。在编译该程序时,系统对于p=arr语句会给出一个不能赋值的错误提示。为什么?前边学习时我们不是一直在强调数组名就是数组元素的起始地址吗,而且在一维数组和指针的关系中,我们也确实可以将数组的名字赋给一个基类型相同的指针变量,那么怎么到二维数组中就不行了呢?根据前边所学我们知道,指针相互之间能够赋值的前提是两个指针的基类型应该是一样的。既然不能赋值,说明一维数组的数组名和二维数组的数组名字代表的含义是不一样的,或者说一维数组名字和二维数组名字作为指针时其基地址是不一样的。请参考图7-11。
图7-11 一维数组和二维数组基地址示意图
如图7-11所示,此时arra作为一维数组的首地址,其值等价于&a[0],而a[0]是一个int型的单元,所以arr是一个指向int类型单元的指针。而arrb作为二维数组的名字,代表的也是数组arrb的起始地址(即&arrb[0],同一维数组一样),但是arrb的0单元中保存的是一个长度为3的int型的数组,所以arrb实质上是一个指向数组的指针。因此在上边的程序中,我们将二维数组的名字赋给一个指向整型的指针变量是错误的,因为二者所指向的对象不同。可以用一个例子来验证。
【例7-11】
可以看到,在一维数组arra中,两个相邻单元相差4字节,因为一个int型单元占4个字节,也就是说arra是一个指向int型单元的指针,所以arra+1是加了4个字节;而arrb和arrb+1的值相差12个字节,这是因为arrb的每一个单元中存放的是一个长度为3的int型数组,因此arrb的一个单元的长度为3×4=12个字节,这说明arrb指向的是一个长度为3的int数组,arra和arrb二者所指向的对象是不同的。
总的来说,C语言中处理二维数组时仍然是按照一维数组的方式来处理,即把二维数组看成是每个单元存放一维数组的一维数组,其地址关系和一维数组中是相同的,完全可以使用一维数组中的地址关系来表示。如果有定义int arr[4][3],则arr代表其0单元的地址,arr+1是该数组1单元的地址,而arr+i就是其i号单元的地址。如图7-12所示。
(www.xing528.com)
图7-12 二维数组中的地址关系
由图7-12可以看出,arr+i就是arr数组第i个单元的地址(同一维数组一样),而第i个单元对应的是二维数组的第i行,所以可以将arr+i看成是二维数组arr的行指针。在一维的存储结构中,arr[i]是数组arr的第i个单元,同时也可以将它看成是第i个单元中的一维数组的名字,因此arr[i]就是i号单元中的一维数组的起始地址,此时arr[i]+0就是arr[i]数组的第0个单元的地址(&arr[i][0]),arr[i]+j即arr[i]数组第j个单元的地址(&arr[i][j]),这里用到的仍旧是一维数组中的地址关系。由此可以将arr[i]看成是二维数组第i行的列地址,及当arr[i]+j时,该指针将指向第i行中的第j列,如图7-12所示。另外由于arr[i]等价于*(arr+i),所以*(arr+i)+j等价于arr[i]+j,均代表arr数组第i行第j列的地址&arr[i][j]。二维数组中的地址关系总结如表7-1。
表7-1 二维数组arr中的地址关系
3.用指针访问二维数组
明白了二维数组中的指针关系后,可以使用二维数组中的地址关系,通过指针来间接访问二维数组中的单元。
【例7-12】用指针输入输出二维数组中的元素。
请同学们自己上机验证程序运行结果。
4.用指向数组元素的指针访问二维数组
由图7-12可以看出,二维数组在内存中存放时,其真实的存储结构仍然是一维的,因此可以使用前边学过的指向数组元素的指针将二维数组作为一维数组来访问。
【例7-13】使用指向数组元素的指针访问二维数组。
程序中p=arr[0],相当于p=&arr[0][0],因为arr[0]就是arr数组0单元中的一维数组的名字,是该数组的起始地址,即arr[0][0]单元的地址。由于p是指向整型单元的指针,初始时指向了arr[0][0]单元,因此当执行p++时,指针p将会指向下一个整型单元(arr[0][1]),以此类推,当指针p不停加1时,就可以访问到数组中的每一个单元。
由此可见,根据二维数组的存储结构,完全可以利用指向数组元素的指针,将它转换为一维数组来处理。
免责声明:以上内容源自网络,版权归原作者所有,如有侵犯您的原创版权请告知,我们将尽快删除相关内容。