The big problem is that p and &x are different types.
The pointer given by &x is a pointer to the whole array x, not to a single element, and its type is int (*)[3], not int *.
If you want to get a pointer to the first element of x then use &x[0], or plain x (as that decays to &x[0]).
And even while the types of &x and &x[0] are different, they both point to the same location (as your (invalid) printouts indicates). This can be seen if you attempt to visualize the array x in memory:
+------+------+------+
| x[0] | x[1] | x[2] |
+------+------+------+
^
|
&x
|
&x[0]
As I already mentioned in a comment, to print pointers you need to use the %p format specifier. Mismatching formatting specifier and argument type leads to undefined behavior.
What's more, the %p format specifier is for void * pointers, so you need to cast the pointers (unless they are already void * of course):
printf("%p %p \n", (void *) p, (void *) x);