我遇到了多维数组的问题。也许解决方案更容易。
int arr[2][2]; //multidimensional array
我的简单问题是:为什么
arr [0] [2]和arr [1] [0] 要么 arr [1] [2]和arr [2] [0]
在我的情况下,在同一地址? 我在Linux和Windows环境中检查了这个问题。问题是一样的。我已经检查了教程和其他来源,但没有答案。
答案 0 :(得分:1)
指针&arr[0][2]
是数组arr[0]
的一个结尾指针。这个地址与下一个数组arr[1]
的第一个元素&arr[1][0]
的地址相同,因为数组在内存中是连续布局的。
arr[2][0]
有点诡计:arr[2]
不是有效访问,但&arr[2]
是数组arr
的一个结尾指针。但由于无法取消引用该指针,因此谈论arr[2][0]
是没有意义的。 arr
没有第三个元素。
答案 1 :(得分:0)
C将多维数组存储在所谓的row-major order中。在该配置中,单行的所有数据都存储在连续的内存中:
arr[2][2] -> r0c0, r0c1, r1c0, r1c2
备选方案是列主要订单,它会连续放置列。
由于您已将行的长度(列数)指定为2,因此访问第2列(第三列)将计算“环绕”到下一行的地址。
数学看起来像:
&(arr[row][col])
= arr # base address
+ row * ncols * sizeof(element)
+ col * sizeof(element)
= arr + sizeof(element) * (row * ncols + col)
在您的情况下,arr[0][2]
为arr + (0*2 + 2) * sizeof(int)
,而arr[1][0]
为arr + (1*2 + 0)*sizeof(int)
。
您可以对其他变体进行类似的数学运算。
答案 2 :(得分:-1)
数组索引与指针算法相同(实际上,在应用[]
- 运算符之前,数组名称首先被转换(“衰减”)为指向第一个元素的指针):
arr[r][c] <=> *(arr + r * INNER_LENGTH + c)
您的数组每个维度有两个条目。在C索引中,从0
开始,因此对于每个维度,有效索引为0
和1
(即total_entries - 1
)。这首先使你的三个表达成为可能:
arr[0][2] // [outer dimension/index][inner dimension/index]
arr[1][2]
arr[2][0]
我们有这些案例:
0
:相同。如果我们对维度使用不同的长度并查看数据的存储方式,内存中的确切内容可能会变得更加清晰:
int arr[3][2];
这是“包含2个int
元素的3个数组的数组”。由于内存布局,最左边的维度称为“外部”,最右边的维度称为“内部”维度:
arr[0][0] // row 0, column 0
arr[0][1] // row 0, column 1
arr[1][0] // ...
arr[1][1]
arr[2][0]
arr[2][1]
使用上面的公式,&arr[0][2]
(arr + 0 * 2 + 2
)会产生与&arr[1][0]
(arr + 1 * 2 + 0
)相同的内容,等等。但请注意,虽然地址相同,第一个版本不能被取消引用,编译器可能会生成错误的代码等。
答案 3 :(得分:-2)
C中的数组索引类似于将索引的值添加到第一个元素的地址。
在您描述的多维数组中,每个维度上有2个元素:0和1.当您引入大于该数字的数字时,您将引用该维度之外的元素。从技术上讲,这是一个数组越界错误。
地址分解如下:
arr[0][0]
- &arr[0] + 0
arr[0][1]
- &arr[0] + 1
arr[1][0]
- &arr[0] + 2
arr[1][0]
- &arr[0] + 3
当您编写arr [0] [2]时,您引用地址&amp; arr [0] + 2,这与arr [1] [0]相同。这一切都只是指针数学,所以一旦你知道它是如何工作的,你就可以很容易地解决它。
答案 4 :(得分:-2)
您可以将二维数组视为一维长数组:
[00][01][10][11]
使用指针算术,这个长一维数组的另一种表示是:
[00][01][02][03]
因此,查看单元格[10]
与在指针算术视点中查看单元格[20]完全相同。