carrayspointersmultidimensional-array

How does `*((*arr+(i*3))+j)` work when printing a 2D array `arr`?


Code:

#include <stdio.h>

int main(void)
{
    int arr[2][3] = {{1,2,3},{4,5,6}};
    int i, j;

    for(i = 0; i < 2; i++)
    {
        for(j = 0; j < 3; j++)
        {
            printf("%d ", *((*arr+(i*3))+j));
        }
        printf("\n");
    }

    return 0;
}

I'm surprised how the above code gives the output:

1 2 3   
4 5 6

I know that *(arr+i) == arr[i] and also that I should be using arr[i][j] instead of making everything more complicated, but I don't understand how *((*arr+(i*3))+j) works.

In my understanding, *((*arr+(i*3))+j) can be simplified to *((*arr)+(i*3)+j) since the *(indirection operator) has the most precedence here.

So, when i is zero and j iterates through, 0 to 2, the expression is the same as arr[0][j] which prints the integers of the first subarray.

My confusion builds up when i becomes 1. The next three expressions will be *((*arr)+(1*3)+0), *((*arr)+(1*3)+1) and *((*arr)+(1*3)+2) which can be simplified to arr[0][3], arr[0][4] and arr[0][5].

How does this print the last three values?


Solution

  • int arr[2][3] = {{1,2,3},{4,5,6}};
    

    In memory :

    1 | 2 | 3 | 4 | 5 | 6
    each number on an adjacent memory "cell" the size of an int, in this order
    

    Second line : i = 1 j = 0

    *((*arr+(i*3))+j)) means *((*arr + 3) + 0)-> *({1, 2, 3} + 3) -> *({4, 5, 6}) = 4
    

    Keep in mind that x[n] is equivalent to *(x + n), whatever x or n. (This also means arr[1] is equivalent to *(arr + 1), *(1 + arr) and so 1[arr] which I find funny)

    Here arr[1][0] : x is arr[1] and n is 0 so first equivalence: *(arr[1] + 0)
    Second x is arr and n is 1 so *(*(arr + 1) + 0).
    Finally arr + 1 means the adress at arr + sizeof(*arr), which means: (arr + 1) is equivalent to (*arr + 3) because *arr is arr[0] which is of type int[3]