c语言里二维数组是怎样实现的?

以前一直以为二维数组是一个存储一维数组的数组 每个元素都是子数组的头指针
但是看了一篇文章 似乎是说并没有这回事 a [3] [4]只是连续的12个空间 a是第一个空间的头地址 a[0]是第一个一维数组的头地址 也是第一个空间的地址 a[1]是第二个数组的头地址 实际上是第5个空间的地址 多维数组只是把一个一维数组划分成了很多小块?
怎么理解才是对的呢?

阅读 3.7k
2 个回答

更新

补一个 a[3][4] 的内存分布

a = [3][4]
/* 内存中 */

a[0] <-> [b[0], b[1], b[2], b[3]],
a[1] <-> [c[0], c[1], c[2], c[3]],
a[2] <-> [d[0], d[1], d[2], d[3]];

/* a 中元素指向的地址 */
a[00] -> b[0]
a[01] -> c[0]
a[02] -> d[0]
a[03] -> b[1]
a[04] -> b[2]
a[05] -> b[3]
a[06] -> c[1]
a[07] -> c[2]
a[08] -> c[3]
a[09] -> d[1]
a[10] -> d[2]
a[11] -> d[3]
...

所以 a[1] 指向的是 c[0](指向地址),而 c[0] 实质上在整个 a的内存 中排第五位(内存分布)

原答案

连续 说的是内存中的分布

其实看内存图解的时候我也有点晕,做了一些思考后有如下猜测:

一个二维数组,前几个元素是记录了几个内部一维数组的头地址在整个外部一维数组中的偏移位置。

也就是说

a = [2][2]
/* 内存中 */
a[0] -> b[0]
a[1] -> c[0]
a[2] -> b[0]
a[3] -> c[1]
...

因为数组长度是不可变的,一旦编译,内存地址直接分配,只要知道子数组的首地址,可以直接根据偏移快速定位:

a[n][m] -> a[n] + m

a[1][1] -> a[1] + 1 -> c[0] + 1 -> c[1]

对于多维数组的话:

a = [2][2][2]
/* 内存中 */
a[0] -> b(0)[0] -> c[0]
a[1] -> b(1)[0] -> d[0]
a[2] -> b(0)[1] -> e[0]
a[3] -> b(1)[1] -> f[0]
a[4] -> c[1]
a[5] -> d[1]
a[6] -> e[1]
a[7] -> f[1]
...
a[x][y][z] -> a[x][y] + z -> (a[x] + y) + z

a[0][1][0] -> a[0][1] + 0 -> (a[0] + 1) + 0 -> c[0] + 1 -> c[1]

注: 对于 a[0] + 1 是说把 a[0] 指向的地址(也就是 c[0] )下移一次,不是代数运算

如果有说错的还请大家斧正!

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进