首先,我要说明的,在C语言中,把“多维数组”叫做“数组的数组”更好理解一下。(下面我就统一称之为“数组的数组”)
有的教程中喜欢将数组的数组用矩阵表示,不过我更趋向于直线表示,如下图(定义数组的数组int ga[2][3][5])
(如果图片太小,建议保存到电脑上对其放大查看)
我对数组的数组的理解(以ga[2][3][5]为例): 即为数组的数组,数组里面包含数组,数组作为另一个数组的元素。
int ga[2][3][5] = {ga_1[1], ga_1[2]}
= {{ga_2[0], ga_2[1], ga_2[3]},
{ga_2[0], ga_2[1], ga_2[3]}}
= {{ga_3[0], ga_3[1], ga_3[2], ga_3[3], ga_3[4]},
{ga_3[0], ga_3[1], ga_3[2], ga_3[3], ga_3[4]},
...(此处省略3个,上下一个6个(ga_3[0]~ga_3[4])的)
{ga_3[0], ga_3[1], ga_3[2], ga_3[3], ga_3[4]}}; //可能这种表达有点问题!!!欢迎指出 :)
首先,我们看一下指针和一维数组的关系:
int one[5] = {0};
int *p1=one; //一维数组就是这样子的,没错吧?
然后,再来看看指针与二维数组的关系:
int two[3][5] = {0};
int (*p2)[5] = two; //注意和上述一维数组的关系和区别噢!
最后我们看看指针与三位数组的关系:
int three[2][3][5] = {0};
int (*p3)[3][5] = three; //这下你应该总结出来了一点规律了吧?
是的,四维数组、五维数组、...差不多都是这样子的。
下面开始解释其原因:(请始终牢记“多维数组”即是“数组的数组”)
1、上述三维数组中的ga[2]可以看作一维数组ga_1[2],其元素是ga_1[0],ga_1[1]。
2、ga_1[0]又是一个数组,其元素是ga_2[0],ga_2[1],ga_2[2],亦即是ga_1[0]可以表示为ga_1[0][3],同理有ga_1[1][3](请注意颜色!);
3、当然ga_2[0] 亦可以表示为ga_2[0][5],同理...;
4、总结的表达式就为上述很长的那个连等式;
5、还有问题需要注意,就是分割出来的子数组的首指针是指向什么位置的;
5、不知道我解释的对不对,您能看懂么? 欢迎指出错误!!!
既然上面有指针p1,p2,p3与数组有关联了,那么现在开始用指针对数组元素访问:
p1:
printf( " one[%d] = %d\n " , i, * (p + i));
p2:
for (; i < 3 ; i ++ )
for (j = 0 ; j < 5 ; j ++ )
printf( " two[%d][%d] = %d\n " , i, j, * ( * (p2 + i) + j));
p3:
for (; i < 2 ; i ++ )
for (j = 0 ; j < 3 ; j ++ )
for (k = 0 ; k < 5 ; k ++ )
printf( " three[%d][%d][%d] = %d\n " , * ( * ( * (p3 + i) + j) + k));
【提示:如果你想愿意可以用指针访问数组的方式,和使用数组下标访问的方式,将数组各个元素的地址打印出来,然后比较一下。打印地址的控制符是"%p"】。
另外需要注意的是:
1、在*(*(*(p3+i)+j)+k)中,当执行“p3+i”的时候数组步长为“4*3*5=60”,当执行“...+j”的时候步长为“4*5=20”,当执行“...+k”的时候步长为“4”,这里的“4”都是指int类型所在字节数。(关于数组步长的概念,请大家查阅其相关资料。)
2、int (*r)[5] = ga[1]中g[1]指的是第二个ga_2[0]地址,亦即是ga[2][3][5]被看作ga_2[2]了;
int *t = g[1][1]中g[0][0]指的是第二个ga_2[1]地址,亦即是ga[2][3][5]被当作ga_1[2][3]了。
(这点可能有点难理解,建议上机操作一次。)
ps:貌似用指针和下标访问的多位数组的效率是一样的,到底使用那种方式看自己对其掌握的熟练程度。但是二者所代表的含义不一样,请参考本博博文:http://www.cnblogs.com/ziwuge/archive/2011/10/24/2194813.html 中第三篇模版里提到的内容。