To be correct, first, your print statement should look like
printf("a: %p\n&a: %p", (void *)a, (void *)&a);
because %p expects a void * argument. Please, note, printf() being a variadic function, implicit conversion (cast) won't take place, so, the casting is required.
Now, that said, a being an array,
a is of type int [4]
&a is if type int (*)[4]
(but, both will return the same address, FWIW.) You can also see this answer.
OTOH, in your case, p is of type int *.
That's why your compiler warns you about the type mismatch in the assignment.