MEMORY MAP for 2d / multidimensional arrays

断了今生、忘了曾经 提交于 2019-12-13 00:08:56

问题


Can anyone please explain visually as to how the 2D array is stored in memory as: a , &a, &a[0] , a[0] all have the same address... It seems like a pointer pointing to itself in a way...and that cant be right... This has been bugging me for nearly a year and searching on the web has lead me to no apt answer as well..... help is really appreciated....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]) );
}

OUTPUT

&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

Don't refer me to Memory map for a 2D array in C ... that didnt help ...


回答1:


So the array a is one object taking up a block of memory:

| a                                                         |

It's an array of length 2, so if we draw in the elements that make it up it looks like this:

| a[0]                        | a[1]                        |

a[0] in turn is an array of length 3, and looks like this:

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

a[1] looks the same, so we can redraw the array a to look like this:

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

Notice that a, a[0] and a[0][0] are all located at the same point in memory: the start of the object a. However, they do have different sizes: a is the entire "2D array", a[0] is a regular array, and a[0][0] is a single `int.

This explains why &a, &a[0] and &a[0][0] are the same addresses (though they have different types) - they're the addresses of things located at the same point in memory.

Additionally, there's a rule that if an array is evaluated in an expression where it's not the subject of the unary & or sizeof operators, it evaluates to a pointer to its first element: that is, using a plain a is equivalent to &a[0]. Since a[0] is also an array, using a plain a[0] is equivalent to &a[0][0]. This explains why a and a[0] also evaluate to the same addresses as &a, &a[0] and &a[0][0].

The fact that the address of an array and the adddress of the first element in that array are the same isn't really surprising: the same thing happens with struct, too. Given:

struct { int a; int b; } x;

You'll find that &x and &x.a are the same address (albeit with different types).




回答2:


Except when it is the operand of the sizeof _Alignof, or unary & operators, or is a string literal being used to initialize another array in a declaration, an expression of type "N-element array of T" will be converted to an expression of type "pointer to T" and the value of the expression will be the address of the first element in the array.

Assume the following memory map (assumes little-endian, 4-byte ints; addresses pulled out of thin air):

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]

Going by the rule mentioned above, the expression a will be converted from type "2-element array of 3-element array of int" to "pointer to 3-element array of int", and the value of the expression will be the address of the first element of the array. The first element of a is a[0], and the address of a[0] is 0xfffebc00.

Similarly, the expression a[0] will be converted from type "3-element array of int" to "pointer to int", and its value will be the address of the first element of the array. The first element of a[0] is a[0][0], and its address is ... 0xfffebc00.

The expression &a is one of the exceptions to the rule above. In this case, a is not converted to a pointer type before applying the & operator; the type of the expression is "pointer to 2-element array of 3-element array of int" (int (*)[2][3]), and its value is the address of a, which is ... 0xfffebc00.

Similarly, the expression &a[0] has type "pointer to 3-element array of int" and its value is the address of a[0], which is ... 0xfffebc00.

Hopefully the type and value of &a[0][0] should be obvious.

So yes, the expressions a, &a, *a, a[0], &a[0], and &a[0][0] all yield the same value, but their types are different: int (*)[3], int (*)[2][3], `int *, int *, int (*)[3], and int *, respectively.



来源:https://stackoverflow.com/questions/12952708/memory-map-for-2d-multidimensional-arrays

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!