C语言 C 中二维数组的内存映射

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/6673719/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-02 09:07:38  来源:igfitidea点击:

Memory map for a 2D array in C

cmultidimensional-array

提问by user366312

Do you think what this discussionabout memory-map of 2D array is correct? Especially this photo?Can you explain the theory?

你认为这个关于二维数组内存映射的讨论是正确的吗?尤其是这张照片?你能解释一下这个理论吗?

Suppose we declare a 2D array in C like this:

假设我们像这样在 C 中声明一个二维数组:

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

Now, according to this discussion, the memory would be arranged like the following:

现在,根据这个讨论,内存将被安排如下:

enter image description here

在此处输入图片说明

Now, I have written the following code to test this theory:

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

#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...
*/

Why the first 4 outputs are same?

为什么前 4 个输出相同?

采纳答案by hugomg

Your code just uses a plain multidimensional array, but the image describes an array of pointers, like the kind you usually make when malloc-ing things.

您的代码仅使用一个普通的多维数组,但图像描述了一个指针数组,就像您在 malloc 处理事物时通常使用的那种。

A multidimensional array is basically just a normal, flattened, array (in memory) with some extra syntatic sugar for accessing. So while it is possible to get a pointer from arr[i], there isn't an extra "variable" just to store this, as happens in your image.

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

To correct the image, remove the parts with the arr[0], arr[1]...and change the value of arrto 1245039(the same as &arr[0][0]).

要校正图像,请删除带有 的部分arr[0], arr[1]...并将其值更改arr1245039(与 &arr[0][0] 相同)。

回答by Chris Cooper

See my question here.

在这里看到我的问题。

That is not the way you access information about 2-d arrays. In fact, you can just think of them as 1-d, where you multiply and add the indices in a special way.

这不是您访问二维数组信息的方式。事实上,您可以将它们视为 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}};

These are formatted exactly the same in memory, and they look like this:

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

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

So to get the 8element, you can either ask for x[8], or y[1][3].

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

For the second way, you can think of it as (1 * 5) + 3.

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

This is why your first 4 were the same. You have:

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

  • arr: this is the address of the start of the array
  • arr[0]: this is address of the start of the first sub-array, which is the same as the start of the overall array
  • &arr[0][0]: this is the address of first element of the first sub-array, also the start of the overall array
  • arr[0][0]: this is the value stored in the first element of the first sub-array.
  • arr: 这是数组的起始地址
  • arr[0]: 这是第一个子数组的起始地址,与整个数组的起始地址相同
  • &arr[0][0]: 这是第一个子数组的第一个元素的地址,也是整个数组的开始
  • arr[0][0]:这是存储在第一个子数组的第一个元素中的值。

回答by Richard Schneider

The first four outputs are the same why of obtaining the address of the first element in the array, i.e. &arr[0][0]. The last output is its content.

前四个输出与为什么获取数组第一个元素的地址相同,即&arr[0][0]。最后一个输出是它的内容。

回答by shelleybutterfly

well, as far as i recall, in C++ (and i think C, although that's not my forte) a 2d array declared as Values[][]is generally (don't know if always) implemented as an array of C-style arrays. however, when you declare them on the stack (e.g. a local variable), i believe the memory formatting is different.

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

so, when you declare a local variable everything is laid out as ifit were just a 1d array, and you get things laid out such that you can actually cast to a pointer and then access as a 1D array.(!) however, it still is recognized the same way as a normal 2D array within the scope of the declaration, and possibly if you pass to a parameter which is declared with the []notation.

所以,当你声明一个局部变量时,一切都被布置就像一个一维数组一样,你得到的东西布置得这样你就可以实际转换为一个指针,然后作为一个一维数组访问。(!)但是,它仍然以与声明范围内的普通二维数组相同的方式识别,并且可能如果您传递给使用该[]符号声明的参数。

but, if you allocate one of these on the heap (e.g. global or static or via new), the story is different. now, the memory is laid out as an actual array of arrays, and so the actual results of the memory locations you index if you cast to a 1D array and index is now going to be pointers instead.

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

i verified my recall by doing the following: i created int HeapArray[3][3];as a global, and int StackArray[3][3];as a local (both with initializers of { { 10, 20, 30 }, {40, 50, 60}, {70, 80, 90 } }). inside my function i cast both of them to an int pointer, int* ptrHeapArray = (int*)HeapArray;and int* ptrStackArray = (int*)StackArray;and then looked at the return value of the 0th element of each.

我通过执行以下操作验证了我的回忆:我创建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个元素的返回值。

[edit: whoops, i had them reversed; fixed now]

[编辑:哎呀,我把它们颠倒了;现在固定]

ptrStackArray[0]was equal to 10

ptrStackArray[0]等于 10

ptrHeapArray[0]was equal to a pointer to int[3];

ptrHeapArray[0]等于一个指向 int[3] 的指针;

so i think my limited recall is accurate. :) hope this helps!

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