用于2d /多维阵列的MEMORY MAP

时间:2012-10-18 10:36:42

标签: c arrays memory memory-management 2d

任何人都可以解释直观关于2D数组如何存储在内存中: a,& a,& a [0],a [0]都有相同的地址...... 这似乎是一个指针指向自己的指针......而且不能正确...... 这已经让我困扰了将近一年,在网上搜索也让我无法回答.....帮助真的很感激.... thanx

enter code here

#include<stdio.h>

int main()
{
    int a[2][3]={10,20,30,40,50,60};

    int row =0,col=0;

    printf("&a = %d ",&a);    
    printf("\na = %d ",a);
    printf("\n&a[0] = %d ",&a[0]);
    printf("\na[0] = %d ",a[0]);
    printf("\n&a[1] = %d ",&a[1]);
    printf("\na[1] = %d ",a[1]);
    printf("\n&a[0][0] = %d ",&a[0][0]);

    int *p;
    printf("\n\n sizeof(p) = %d ",sizeof(p) );

    printf("\n\n sizeof(a) = %d ",sizeof(a) );
    printf("\n\n sizeof(&a) = %d ",sizeof(&a) );
    printf("\n\n sizeof(&a[0]) = %d ",sizeof(&a[0]) );
    printf("\n\n sizeof(a[0]) = %d ",sizeof(a[0]) );
    printf("\n\n sizeof(&a[1]) = %d ",sizeof(&a[1]) );
    printf("\n\n sizeof(a[1]) = %d ",sizeof(a[1]) );
    printf("\n\n sizeof(&a[0][0]) = %d ",sizeof(&a[0][0]) );
}

输出

&a = 2293536
a = 2293536
&a[0] = 2293536
a[0] = 2293536
&a[1] = 2293548
a[1] = 2293548
&a[0][0] = 2293536

sizeof(p) = 4

sizeof(a) = 24

sizeof(&a) = 4

sizeof(&a[0]) = 4

sizeof(a[0]) = 12

sizeof(&a[1]) = 4

sizeof(a[1]) = 12

sizeof(&a[0][0]) = 4

不要把我推荐给那些没有帮助的Memory map for a 2D array in C ......

2 个答案:

答案 0 :(得分:5)

所以数组a是一个占用内存块的对象:

| a                                                         |

这是一个长度为2的数组,所以如果我们绘制构成它的元素,它看起来像这样:

| a[0]                        | a[1]                        |

a[0]又是一个长度为3的数组,看起来像这样:

| a[0][0] | a[0][1] | a[0][2] |

a[1]看起来一样,所以我们可以重新绘制数组a,如下所示:

| a[0][0] | a[0][1] | a[0][2] | a[1][0] | a[1][1] | a[1][2] |

请注意,aa[0]a[0][0]都位于内存中的同一点:对象的开头a。但是,它们的大小不同:a是整个“2D数组”,a[0]是常规数组,a[0][0]是单个`int。

这解释了为什么&a&a[0]&a[0][0]是相同的地址(尽管它们有不同的类型) - 它们是位于内存中同一点的事物的地址。

此外,还有一条规则,如果一个数组在一个表达式中进行求值,而该表达式不是一元&sizeof运算符的主题,那么它将计算为指向其第一个元素的指针:即,使用普通a相当于&a[0]。由于a[0]也是一个数组,因此使用普通a[0]等同于&a[0][0]。这解释了为什么aa[0] 还评估与&a&a[0]&a[0][0]相同的地址。

数组的地址和该数组中第一个元素的adddress相同的事实并不令人惊讶:同样的事情也发生在struct上。给出:

struct { int a; int b; } x;

您会发现&x&x.a是相同的地址(虽然类型不同)。

答案 1 :(得分:1)

除非它是sizeof _Alignof或一元&运算符的操作数,或者是用于初始化声明中的另一个数组的字符串文字,否则 “N-element array of T”类型的表达式将转换为“指向T的指针”类型的表达式,表达式的值将是第一个元素的地址在数组中。

假设以下内存映射(假设是little-endian,4字节int;地址是凭空消失的:

Item         Address          00   01   02   03    Sub array    Sub array element
----         -------          --   --   --   --    ---------    -----------------
   a         0xfffebc00       00   00   00   0a    a[0]         a[0][0]
             0xfffebc04       00   00   00   14                 a[0][1]
             0xfffebc08       00   00   00   1e                 a[0][2]
             0xfffebc0c       00   00   00   28    a[1]         a[1][0]
             0xfffebc10       00   00   00   32                 a[1][1]
             0xfffebc14       00   00   00   3c                 a[1][2]

按照上面提到的规则,表达式 a将从“{-1}}的3元素数组的2元素数组”转换为“指向3元素数组int“,表达式的值将是数组第一个元素的地址。 int的第一个元素是aa[0]的地址是a[0]

类似地,表达式0xfffebc00将从类型“{-1}}的3元素数组”转换为“指向a[0]的指针”,其值将是第一个的地址数组的元素。 int的第一个元素是int,其地址是...... a[0]

表达式a[0][0]是上述规则的例外之一。在这种情况下,0xfffebc00在应用&a运算符之前不会转换为指针类型;表达式的类型是“指向{-1}}(a)的3元素数组的2元素数组的指针,其值是&的地址,它是... 。int

类似地,表达式int (*)[2][3]具有类型“指向a的3元素数组的指针”,其值为0xfffebc00的地址,即... {{1} }。

希望&a[0]的类型和价值应该是显而易见的。

是的,表达式inta[0]0xfffebc00&a[0][0]a&a都会产生相同的,但其类型不同:*aa[0]&a[0]&a[0][0]int (*)[3]int (*)[2][3],分别