C中二维数组的内存映射

时间:2011-07-13 03:23:38

标签: c multidimensional-array

您认为关于2D阵列的内存映射的this discussion是正确的吗? Especially this photo?你能解释一下这个理论吗?

假设我们在C中声明一个2D数组:

int arr[3][3]={10, 20, 30, 40, 50, 60, 70, 80, 90};

现在,根据这个讨论,内存将按如下方式排列:

enter image description here

现在,我编写了以下代码来测试这个理论:

#include <stdio.h>

main()
{
    int arr[3][3]={10, 20, 30, 40, 50, 60, 70, 80, 90};
    printf("      arr==%d\n", arr);
    printf("  &arr[0]==%d\n", &arr[0]);
    printf("   arr[0]==%d\n", arr[0]);
    printf("&arr[0][0]=%d\n", &arr[0][0]);
    printf(" arr[0][0]=%d\n", arr[0][0]);
}
/*
Output:
========
      arr ==1245028
  &arr[0] ==1245028
   arr[0] ==1245028
&arr[0][0]==1245028
 arr[0][0]==10
Press any key to continue...
*/

为什么前4个输出相同?

4 个答案:

答案 0 :(得分:13)

<强> See my question here.

这不是您访问有关二维数组的信息的方式。实际上,您可以将它们视为1-d,在这里您可以以特殊方式乘以和添加索引。

e.g。

int x[10] = {0,1,2,3,4,5,6,7,8,9};
int y[2][5] = {{0,1,2,3,4},{5,6,7,8,9}};

这些格式在内存中完全相同,它们看起来像这样:

|0|1|2|3|4|5|6|7|8|9|

因此,要获取8元素,您可以要求x[8]y[1][3]

对于第二种方式,您可以将其视为(1 * 5) + 3

这就是为什么你的前4个是相同的。你有:

  • arr:这是数组开头的地址
  • arr[0]:这是第一个子数组开始的地址,与整个数组的开头相同
  • &arr[0][0]:这是第一个子数组的第一个元素的地址,也是整个数组的开头
  • arr[0][0]:这是存储在第一个子数组的第一个元素中的值。

答案 1 :(得分:8)

你的代码只使用一个简单的多维数组,但是图像描述了一个指针数组,就像你在编写事物时通常所做的那样。

多维数组基本上只是一个普通的,扁平的数组(在内存中),有一些额外的合成糖可供访问。因此,虽然可以从arr [i]获取指针,但是没有额外的“变量”来存储它,就像在图像中一样。

要更正图像,请使用arr[0], arr[1]...删除部分,并将arr的值更改为1245039(与&amp; arr [0] [0]相同)。< / p>

答案 2 :(得分:0)

前四个输出与获得数组中第一个元素的地址的原因相同,即&amp; arr [0] [0]。最后一个输出是它的内容。

答案 3 :(得分:0)

好吧,据我所知,在C ++中(我认为C,虽然这不是我的强项)一个声明为Values[][]的二维数组通常(不知道是否总是)实现为一个数组C风格的数组。但是,当你在堆栈上声明它们(例如一个局部变量)时,我相信内存格式是不同的。

所以,当你声明一个局部变量时,所有的内容都是,好像它只是一个1d数组,并且你得到了一些东西,你可以实际投射到一个指针,然后访问为一个数组。(!)然而,它仍然被认为与声明范围内的普通2D数组相同,并且可能传递给使用[]表示法声明的参数。

但是,如果你在堆上分配其中一个(例如全局或静态或通过新),故事就不同了。现在,内存被布局为一个实际的数组数组,因此如果你转换为一维数组,索引的内存位置的实际结果现在将成为指针。

我通过执行以下操作验证了我的回忆:我创建了int HeapArray[3][3];作为全局,int StackArray[3][3];作为本地(两者都使用{ { 10, 20, 30 }, {40, 50, 60}, {70, 80, 90 } }的初始值设定项)。在我的函数中,我将它们都转换为int指针int* ptrHeapArray = (int*)HeapArray;int* ptrStackArray = (int*)StackArray;,然后查看每个指针的第0个元素的返回值。

[编辑:哎呀,我让他们逆转;现在修复]

ptrStackArray[0]等于10

ptrHeapArray[0]等于指向int [3];

的指针

所以我认为我的有限回忆是准确的。 :)希望这有帮助!