13

Do you think what this discussion about 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:

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?

user366312
  • 16,949
  • 65
  • 235
  • 452
  • 3
    I think the real question is whether there is a difference between `int **arr` and `int arr[][]` -- none of the answer addresses that. – Soren Jul 13 '11 at 09:27

4 Answers4

17

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.

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 8 element, you can either ask for x[8], or y[1][3].

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

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

  • 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.
Community
  • 1
  • 1
Chris Cooper
  • 17,276
  • 9
  • 52
  • 70
  • Your math is a little off. To get the `8` element you would ask for `x[8]`, not `x[9]`. In addition, the calculation for an element using `y[1][3]` is `(1*5) + 3`. – Hitesh May 23 '13 at 20:28
  • Thanks @Hitesh, I've fixed it. Ironically, I was thinking in terms relative to an imaginary "array start" for my example. – Chris Cooper May 30 '13 at 23:19
11

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.

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.

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

hugomg
  • 68,213
  • 24
  • 160
  • 246
0

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.

Richard Schneider
  • 34,944
  • 9
  • 57
  • 73
0

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.

so, when you declare a local variable everything is laid out as if it 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.

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

ptrStackArray[0] was equal to 10

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

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

shelleybutterfly
  • 3,216
  • 15
  • 32