cpointersmemorymultidimensional-array

Accesing to value of 2D array using pointer arithmetic


I'm studying multy-pointers and I watched this video, where explains that, if we want to access the value of a 2D array, we use double indirection like this:

#include <stdio.h>
#include <stdlib.h>

int main(int argc, char **argv){
    
    int a[2][2] = {{1,2},{3,4}};
    int** p = &a[0][0];

    printf("%d", **p);
    
    return 0;
}

But I get a segmentation fault. If I do instead a single indirection:

    int a[2][2] = {{1,2},{3,4}};
    int** p = &a[0][0];

    printf("%d", *p);

I get the correct value a[0][0] = 1. Now, if I use pointer arithmetic in the single inderection,

    printf("%d", *(p+1));

I get a[1][0] = 3, which makes sense because if I printf("%d", sizeof(p)), I get 8 bytes.

Now my question is, How do I get a[0][1] and a[1][1] using pointer arithmetic?


Solution

  • int** p = &a[0][0];
    

    This is wrong. The type of a[0][0] is int; therefore, the type of &a[0][0] is int *, not int **, and that line should be

    int *p = &a[0][0];
    

    So,

    *p       == a[0][0] == 1
    *(p + 1) == a[0][1] == 2
    *(p + 2) == a[1][0] == 3
    *(p + 3) == a[1][1] == 4
    

    Remember that unless it is the operand of the sizeof, _Alignof, or unary & operators, an array expression will "decay" to a pointer expression and the value of the pointer will be the address of the first element of the array:

    Expression    Type        "Decays" to    Equivalent expression
    ----------    ----        -----------    -----------------------
             a    int [2][2]    int (*)[2]     &a[0]
            *a    int [2]       int *          a[0]
          a[i]    int [2]       int *          &a[i][0]
         *a[i]    int           n/a            a[i][0]
    
            &a    int (*)[2][2] n/a            n/a
         &a[i]    int (*)[2]    n/a            n/a
      &a[i][j]    int *         n/a            n/a
    

    This is important - a 2D array expression decays to a pointer to an array, not a pointer to a pointer.

    If

    a[i] == *(a + i)
    

    then

    a[i][j] == *(*(a + i) + j)
    

    So if you declare a pointer

    int (*p)[2] = a;
    

    then

     p       == &a[0]                // int (*)[2] == int (*)[2]
    *p       ==  a[0]   == &a[0][0]  // int * == int *
    *(p + 1) ==  a[1]   == &a[1][0]  // int * == int *
    
    *(*(p + 1)) == a[1][0]