0

I understand how 1D array pointer works, but I can't understand how 2D array pointer works.

I know that array1[0] == *(array1 + 0), but I have no idea how to use this kind of form in 2D array. And I found out if I use double pointer or '[]'(i don't know what this is), then it works.

  1. How can I access multi-dimensional arrays by using pointer?

  2. Is it ok to use double pointer or '[]'? and if it is, why??

  3. And why *(2Darrayname + number) isn't working?

  4. Is it because of decay something? (I don't know about decay stuff sry)

edit) i already checked these What is array to pointer decay? Pointers in C: when to use the ampersand and the asterisk? Accessing multi-dimensional arrays in C using pointer notation

int main()
{
    int array1[5];
    int array2[5][5];

    f1(array1);
    f2(array2);
}

int f1(int *p1)
{
    for(int i = 0; i<5 ; i++)
    {
        printf("%d", *(p1+i));    //this is ok
    }
}

int f2(int (*p2)[5])
{
    for(int i = 0; i<5 ; i++)
    {
        printf("%d", *(p2+i));    //this one makes error, and gcc says it is 'int *'
        printf("%d", *(p2+i)[1]); //and this one is ok for some reason
        printf("%d", **(p2+i));   //this one too. why is this ok??
    }
}
Delisle
  • 5
  • 3

2 Answers2

0

Assuming the array name to be arr

  1. To access an element of a 2D array: arr[i][j]
  2. Using arr[i] is just an alternate way of saying *(arr + i).
  3. If it's a 2D array then you must de-reference twice to access an element. *(arr + num) would just take you to the base address of the num'th row of the array, hence it doesn't work. So by this all these are equivalent forms.

arr[i][j], *(*(arr + i) + j), *(arr[i] + j)

So arr is a 2D array pointer which means that it stores the address of arr[0] and arr[0] stores the address of arr[0][0], thus arr can be understood as a pointer to a pointer.

0

You're getting confused by the fact that "2D array" is ambiguous in C -- there are two completely different things that can be called a "2D array", which stems from the fact that arrays themselves are 1D, but can be composed of other things (including arrays) and they decay to pointers.

So when someone says "2D array" they might be talking about:

  • an array of arrays
  • an array of pointers (to arrays)

These two things are very different (have different, incompatible types) and need to be created in different ways. However, the syntax for accessing these two things is exactly the same (much the same way that / can be used for dividing integer or floating point values, with very different behavior "under the hood".)

The reason the access syntax is the same is due to pointer decay -- when you have an array of arrays, dereferencing that gives you an array which immediately decays into a pointer. When you have an array of pointers, dereferencing it gives you a pointer directly.


In your example, you have an array of arrays, which immeditely decays into a pointer to array(s) of 5 ints. This shows up as the argument to f2:

int f2(int (*p2)[5])

p2 here is a pointer to array(s) of 5 ints -- it might be a single array or it might be the first element of an array of arrays, which is how you actually call it.

printf("%d", *(p2+i));

p2 is a pointer to array(s) , p2+i gives you a pointer to the ith array of 5 ints. You then dereference this to get an array of 5 ints, which immediately decays into a pointer to the first int in the array (and int *). Since this does not match the printf format (which expects an int), you get undefined behavior.

printf("%d", *(p2+i)[1]);

Here the first step is the same, giving a pointer to the ith array. You then do [1] index on that (remember, postfix operations are always higher precedence than prefix), whichh fetches the (i + 1)th element of the array of arrays. Since this is an array (of 5 ints) it immediately decays into a pointer, which is then dereferenced, giving you an int which matches the printf format. This expression is equivalent to p2[i+1][0] and would be easier to understand as that.

printf("%d", **(p2+i));

Here, this is equivalent to the first case, with an additional * on it. So the int * that resulted in the first case is dereferenced to an int. Equvialent to p2[i][0]

Chris Dodd
  • 119,907
  • 13
  • 134
  • 226