They are not the same. The first (int a[100][100]) is a single variable that is a compound object. The other (int **p) is a collection of arrays that you are using as a data structure for matrices.
If you want to have an actual 2D array in dynamic storage, this is how you do it:
#include <stdlib.h>
int main()
{
int (*m)[100][100];
m = malloc(sizeof *m);
for (int i = 0; i < 100; i++)
for (int j = 0; j < 100; j++)
(*m)[i][j] = 0;
}
Of course, the syntax is a bit weird, and you would rather have a dynamic matrix with variadic number of columns and rows, which is why you would prefer to declare a matrix pointed by int **p.
The reason why a and *a give the same output is because both decay to a pointer to the first element of a, which is a[0][0]. On the other hand, p is a pointer itself, and *p is the contents of the variable pointed by p. They are just as different as they would be if you did this:
int d = 0;
int *p = &d;
printf("%p\n", p);
printf("%d\n", *p);
Now back to your int **p.
Yes, you can access both int a[][100] and int **p with double indexing. However, there is a fundamental difference in the way the compiler treats a[i][j] and p[i][j].
In a[i][j], each a[i] is an array of 100 integer objects. So in order to access the i-th element, and then the j-th element, the compiler has to acess the i*100+j-th element from a[0][0]. This access can be performed in a single step with some index arithmetic.
In v[i][j], each v[i] is a pointer which may point to objects far from each other in memory. In order to acess the element v[i][j], the compiler must first follow p to the array *p, then find the i-th element in this array, which is a pointer to the array p[i]. And then with some pointer arithmetic it will find the j-th element of this array.
int.mallocreturn value of typevoid*and is even undesirable.a, you are really declaring 100 arrays. In this case, it seems that your compiler allocated space for 10,000 ints contiguously. But, when you do the dynamic allocation of p, you have not done that. That's why yourprintfs yield different outputs. Also, note that you should use the%pformat specified with pointers.printf("%p\n", (void*)a);in the first case.ais a 2-D array and treats it so. In the second case the compiler knows thatpis a pointer to an array of pointers, and does the right, but different, thing. Essentially,ais a 1-D array and the compiler figures out the indexing because the memory is contiguous, but in the case ofpthe memory layout is quite different.