Pointer p is also a variable and & operator, when used with pointer variable, gives address of that pointer variable. To print pointer use format specifier %p and, ideally, the argument passed to printf() should be pointer to void. So, you should do
    printf("%p" , (void *)p);
    .....
    printf("%p" , (void *)&p);
can you explain what each of the statement does.
This statement
    printf("%p" , p);
will print address of variable a. [The argument p should be type casted to (void *).]
This statement
    printf("%d" , *p);
will print value of variable a.
In this statement, the format specifier used is wrong, it should be %p
    printf("%d" , &p);
            ^^ 
             |
             +--> %p
when you give correct format specifier %p, it will print address of variable p. [The argument &p should be type casted to (void *).]