要正确回答您的问题,请阅读行优先顺序,这就是多维数组在 C 中的存储方式。维基百科的文章有点过于简洁,但其中一个可能更清楚:
http://webster.cs.ucr.edu/AoA/Windows/HTML/Arraysa2.html
http://archive.gamedev.net/archive/reference/articles/article1697.html
http://www.ibiblio.org/ pub/languages/fortran/append-c.html
也有这个问题。
直接回答您的观点,假设您知道行主要存储的工作原理:
int A[5][2][3]
声明一个长度为 5*2*3 整数的连续内存区域:五个数组,每个数组有两个数组,每个数组三个整数。数组彼此相邻存储在线性内存中,因此
&A[0][0][0] == A
&A[0][0][1] == A+1
&A[0][1][0] == A+(1*3)
&A[3][1][2] == A+(3*(2*3))+(1*3)+2
A[1]
从技术上讲,它不是指针,而是数组。这是一个int [2][3]
数组。但我发现比起考虑A[5][2][3]
一个平坦的内存区域要清楚得多,它长 30 个整数。
A[0][0][0] is the first integer in that region.
A[0][0][1] is the second integer.
A[0][0][2] is the third integer.
A[0][1][0] is the fourth integer in this flat region.
A[0][1][1] is the fifth integer.
And so on until A[1][0][0] is the eleventh integer.
因此地址A[1][0][0]
是过去十个整数A[0][0][0]
;即,&A[1][0][0] - &A[0][0][0] == 10
。因为 C 语言对数组和指针之间的区别非常松散,A[1]
所以当您在表达式中使用它时,它被解释为好像它是一个地址,即使它实际上意味着“五个数组中的两个数组中的第一个元素三个整数”又是“由三个整数组成的两个数组的数组”。
结果是它A[1]
不存储指针,它是一个指针。&A[0][0][0]
从到的每个内存地址都&A[5][2][3]-1
在多维数组中存储一个整数。
您在第 (2) 和 (3) 点中想到的是指向数组的指针数组,它们是不同的。
这用图片更容易解释,这就是为什么你应该找到一本关于 C 数组的合适的教科书或文章。
一般来说,在学习 C 中的指针和数组时,我建议您暂时忘记语言本身,并假装您是 Dennis Ritchie 在具有 56kb 平面 RAM 的 PDP-11 计算机上发明 C。拿一张大方格纸,连续编号它的单元格,假装它代表你的 RAM,每个单元格是一个字节,你可以用铅笔和纸完成你的指针数学。
C 是在那种环境中发明的,了解它的起源将使现代语言更加明智。
附带说明一下,当我尝试编写此答案时,Stack Overflow 的标记语言反复更改并搞砸了我上面的数组示例中的索引。因此,如果您看到那里的任何数字似乎超出了其数组的范围,那么这是编辑器引入的错误。