Search code examples
carrayspointersmultidimensional-arraydouble-pointer

Why do we need to use double pointer to access a 2-D array?


I am trying to understand multidimensional array and pointers, wrote this small program to understand the concept:

#include<stdio.h>
void show(int arr[][2]);
int main()
{
    int z[2][2] = { { 1, 2 },
                    {3, 4 } };
    show(z);
}

void show(int arr[][2])
{

    printf("value of arr = %d", arr);
    printf("\n\nvalue of &arr[0]0] = %d", &arr[0][0]);
}

This code fragment prints the same address which makes sense, but when i edit the show function:

void show(int arr[][2])
{

    printf("value of *arr = %d", *arr);
    printf("\n\nvalue of arr[0]0] = %d", arr[0][0]);
}

*arr still prints the same address while the arr[0][0] as expected prints the integer value , i want to know why i need to use **arr to get the int value , if arr is storing the address it should be dereferenced with *arr, isn't it ?

please help i am having really hard time understanding this concept.. thanks in advance.


Solution

  • If you look at the memory layout of a 2D array, things might become a little bit clearer.

    You have the variable defined as:

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

    Memory:

    z
    |
    v
    +-----+-----+-----+-----+
    |  1  |  2  |  3  |  4  |
    +-----+-----+-----+-----+
    

    Another view of the memory:

    z[0]        z[1]
    |           |
    v           v
    +-----+-----+-----+-----+
    |  1  |  2  |  3  |  4  |
    +-----+-----+-----+-----+
    

    Another view of the memory:

    z[0][0]     z[1][0]
    |   z[0][1] |    z[1][1]
    |     |     |     |
    v     v     v     v
    +-----+-----+-----+-----+
    |  1  |  2  |  3  |  4  |
    +-----+-----+-----+-----+
    

    You can now see that, as far as pure memory location is concerned,

    &z == &z[0] == &z[0][0]
    

    We also that know that when an array decays to a pointer, its value is the address of the first element of the array. Hence, when used in an expression that decays z to a pointer,

    z == &z[0] == &z (from above)
    

    It's puzzling but z and &z evaluate to the same address even though they are of different types.

    Type of z when it decays to a pointer is int (*)[2]. The type of &z is int (*)[2][2].

    Coming to your function, you have:

    void show(int arr[][2]) { ... }
    

    That is equivalent to:

    void show(int (*arr)[2]) { ... }
    

    Why do arr and *arr evaluate to the same value?

    arr evaluates to &z[0] from main. *arr evaluates to z[0] from main, which evaluates to &z[0][0] from main.

    We have already seen that value of &z[0] and &z[0][0] is the same. Hence arr and *arr in show() evaluate to the same address.