多维数组和寻址

时间:2016-05-11 23:13:05

标签: c multidimensional-array

我遇到了多维数组的问题。也许解决方案更容易。

int arr[2][2]; //multidimensional array

我的简单问题是:为什么

arr [0] [2]和arr [1] [0] 要么 arr [1] [2]和arr [2] [0]

在我的情况下,

在同一地址? 我在Linux和Windows环境中检查了这个问题。问题是一样的。我已经检查了教程和其他来源,但没有答案。

5 个答案:

答案 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开始,因此对于每个维度,有效索引为01(即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]完全相同。