1

谁能直观地解释一下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

不要让我参考C 中二维数组的内存映射 ...这没有帮助...

4

2 回答 2

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是整个“二维数组”,a[0]是一个常规数组,并且a[0][0]是一个单一的 `int.

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

此外,还有一条规则,如果数组在不是一元&sizeof运算符的主题的表达式中求值,则它的求值结果为指向其第一个元素的指针:也就是说,使用普通数组a等同于&a[0]. 因为a[0]也是一个数组,所以使用一个普通a[0]的等价于&a[0][0]. 这解释了为什么a并且还评估到与,和a[0] 相同的地址。&a&a[0]&a[0][0]

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

struct { int a; int b; } x;

你会发现它是&x&x.a一个地址(尽管类型不同)。

于 2012-10-18T10:50:07.877 回答
1

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

假设以下内存映射(假设 little-endian,4 字节int;地址凭空提取):

项目地址 00 01 02 03 子数组 子数组元素
---- -------- -- -- -- -- --------- -----
   一个 0xfffebc00 00 00 00 0a [0] a[0][0]
             0xfffebc04 00 00 00 14 a[0][1]
             0xfffebc08 00 00 00 1e [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将从类型“三元素数组的二元素数组int”转换为“指向三元素数组的指针int”,表达式的值将是第一个的地址数组的元素。is的第一个元素,aisa[0]的地址。 a[0]0xfffebc00

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

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

类似地,表达式&a[0]的类型为“指向 3 元素数组的指针int”,其值为 的地址a[0],即0xfffebc00...。

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

所以是的,表达式a, &a, *a, a[0],&a[0]&a[0][0]都产生相同的,但它们的类型不同:分别是int (*)[3], int (*)[2][3], `int *, int *, int (*)[3], 和int *

于 2012-10-18T11:42:19.780 回答