Sandeep Singh
Sandeep Singh

Reputation: 5181

Confusion with Two Dimensional Array

Please consider the following 2-D Array:

int array[2][2] = {
                    {1,2},
                    {3,4}
                  };

As per my understanding: - 'array' represents the base address of the 2-D array (which is the same as address of the first element of the array, i.e array[0][0]).

Please help me clarify this doubt.

Thanks.

Upvotes: 2

Views: 912

Answers (5)

John Bode
John Bode

Reputation: 123468

Arrays are not pointers.

In most circumstances1, an expression of type "N-element array of T" will be converted ("decay") to an expression of type "pointer to T", and the value of the expression will be the address of the first element of the array.

The type of the expression array is "2-element array of 2-element array of int". Per the rule above, this will decay to "pointer to 2-element array of int (int (*)[2]) in most circumstances. This means that the type of the expression *array (and by extension, *(array + 0) and array[0]) is "2-element array of int", which in turn will decay to type int *.

Thus, *(array + i) gives you the i'th 2-element array of int following array (i.e., the first 2-element array of int is at array[0] (*(array + 0)), and the second 2-element array of int is at array[1] (*(array + 1)).

If you want to treat array as a 1-dimensional array of int, you'll have to do some casting gymnastics along the lines of

int *p = (int *) array;
int x = p[0];

or

int x = *((int *) array + 0);


1. The exceptions are when the array expression is an operand of the sizeof or unary & operators, or is a string literal being used to initialize another array in a declaration.

Upvotes: 1

Joseph Carrigan
Joseph Carrigan

Reputation: 439

I like H2CO3's answer. But you can also treat the pointer to the array as an incrementable variable like so:

int array[2][2] = { { 1, 2}, { 3, 4 } };
int *ptr = (int *)array;
int i;
for (i = 0; i < 4; i++) 
{
    printf("%d\n", *ptr);
    ptr++;  
}

the ++ operator works on pointers just fine. It will increment the pointer by one address of it's type, or size of int in this case.

Care must always be used with arrays in c, the following will compile just fine:

int array[2][2] = { { 1, 2}, { 3, 4 } };
int *ptr = (int *)array;
int i;
for (i = 0; i < 100; i++)  //Note the 100
{
    printf("%d\n", *ptr);
    ptr++;  
}

This will overflow the array. If you are writing to this you can corrupt other values in the program, including the i in the for loop and the address in the pointer itself.

Upvotes: 0

wbao
wbao

Reputation: 215

  1. The actual arrangement of a 2-D Array in memory is like a large 1-D Array only.

    yes, the storage area is continuous just like 1D arrary. however the index method is a little different.

    2-D[0][0] = 1-D[0] 
    
    2-D[0][1] = 1-D[1] 
    
    ... 
    
    2-D[i][j] = 1-D[ i * rowsize + j]
    
    ...
    
  2. If I forget about the 2-D array thing & try to treat this array as a simple 1-D array: array[0] = *(array+0) gives the base address of the first array & NOT the element array[0][0]. Why?
    the *(array+0) means a pointer to a array. the first element index in such format should be *((*array+0)+0).

    so finally it should be *(*array)

  3. A 2-D array does not store any memory address (like an Array of Pointers). of course, you can . for example ,

    int * array[3][3] ={ null, };
    
  4. If I know the base address, I must be able to access this memory as a linear 1- Dimensional Array.

    use this formal 2-D[i][j] = 1-D[ i * rowsize + j]...

Upvotes: 3

user529758
user529758

Reputation:

"Thou shalt not fear poynter arythmethyc"...

int array[2][2] = { { 1, 2}, { 3, 4 } };
int *ptr = (int *)&array[0][0];
int i;
for (i = 0; i < 4; i++) {
    printf("%d\n", ptr[i]);
}

Why does this work? The C standard specifies that multidimensional arrays are contigous in memory. That means, how your 2D array is arranged is, with regards to the order of its elements, is something like

array[0][0]
array[0][1]
array[1][0]
array[1][1]

Of course, if you take the address of the array as a pointer-to-int (int *, let's name it ptr), then the addresses of the items are as follows:

ptr + 0 = &array[0][0]
ptr + 1 = &array[0][1]
ptr + 2 = &array[1][0]
ptr + 3 = &array[1][1]

And that's why it finally works.

Upvotes: 5

array[0] is a one-dimensional array. Its address is the same as the address of array and the same as the address of array[0][0]:

assert((void*)&array == (void*)&(array[0]));
assert((void*)&array == (void*)&(array[0][0]));

Since array[0] is an array, you can't assign it to a variable, nor pass it to a function (if you try that, you'll be passing a pointer to the first element instead). You can observe that it's an array by looking at (array[0])[0] and (array[0])[1] (the parentheses are redundant).

printf("%d %d\n", (array[0])[0], (array[0])[1]);

You can observe that its size is the size of 2 int objects.

printf("%z %z %z\n", sizeof(array), sizeof(array[0]), sizeof(array[0][0]));

Here's a diagram that represents the memory layout:

+-------------+-------------+-------------+-------------+
|      1      |      2      |      3      |      4      |
+-------------+-------------+-------------+-------------+
 `array[0][0]' `array[0][1]' `array[1][0]' `array[1][1]'
`---------array[0]---------' `---------array[1]---------'
`-------------------------array-------------------------'

Upvotes: 5

Related Questions