int (*p)[3]; is an array of pointers to int.
int a[3]={10,11,12}; is an array of int. Arrays and pointers share a lot of properties. You can use array notation for pointers for example.
Lets take a normal pointer int *p = a which is the same as int *p = &a[0]. Now the pointer points to the first element of the array. And you can use it the same way as the array.
printf("%d\n", p[0]); //10
printf("%d\n", p[1]); //11
printf("%d\n", p[2]); //12
What you did was getting the address of the array-"pointer" this yields the address of the first element of the array. Because &a == a
This gets written to the first element of your pointer array leaving you with
p[0] == a
p[1] == unknown
p[2] == unknown
by doing *p[0] you get the first element of p (p[0]) and dereference it *.
This is the same as *a or a[0].
But by doing *p[1] you get to an unkown memory location(p[1]) and derefence it *. This is undefined behaviour.
*p[k]is*(p[k]), not(*p)[k].pis an array of three pointers of which one points toa[0]and the others to unkown memory?