dereference a pointer to a pointer casted from array pointer

Viewed 71

Learning C and this confusing me:

#include <stdio.h>

int main(){
    int m[5][5];
    int count = 0;                                                                                                         
    for(int i = 0; i < 5; i++){                                                                                                    
        for(int j = 0; j < 5; j++){
            m[i][j] = count++;
        }
    }                                                                                                                     
    int **p = m;                                                                                                          
    int (*k)[5] = m;                                                                                                      
    printf("%p\t%p\t%p", *p, *k, *m);                                                                                     
    return 0;
} 

that's what has been printed: 0x100000000 0x7ffff1fc9d70 0x7ffff1fc9d70

I'm really confused why dereference *p is 0x100000000, shouldn't it be 0x7ffff1fc9d70?

2 Answers

You’re thinking that m is of type int **, right?

It’s not. If you had done this, it would be:

int *m[5];

That make an array of five pointers to int, so m would be pointer to pointer to int.

However, if you do this:

int m[5][5];

You get enough space for 25 ints, which the compiler will access as a 5x5 two-dimensional array. p points to the beginning of that array. Dereference it, and the compiler reads the beginning of that array and interprets it as a pointer to int. Change the numbers you’re filling it with, and you’ll get different pseudo-pointers.

You probably assume that int m[5][5]; is an array that contains arrays pointers that point on integer array. This assumption is wrong: int m[5][5]; is in practice a flatten 1D array once stored in memory. As a result, the statement int **p = m; is not valid. You should rather use the statement int *p = m;. Once the statement modified, you should now see that *m is not a pointer, but the value of an integer stored in your array (actually the first).

Update:

Since int* and int[5][5] are incompatible types regarding the C standard. A more correct way to perform the array would be int *p = &m[0][0]; rather than just int *p = m;.

Related