I am doing experiements with code to understand pointer

Code:
 #include <stdio.h>#include <stdlib.h>


void foo ( int *p)
{
	int *q = malloc(sizeof(*q));
	if ( q != NULL )
	{


	}	  
 }
int main ()
{


  int *p = NULL;
  
  foo (p);
  
  return 0;
}
This code compile without warning. Program pass the content of pointer p

When I change line to pass location of pointer variable P I get warnings

Code:
  foo (&p);
warnings
Code:
 hello.c:17:8: warning: passing argument 1 of 'foo' from incompatible pointer type [-Wincompatible-pointer-types]   foo (&p);
        ^
hello.c:4:6: note: expected 'int *' but argument is of type 'int **'
 void foo ( int *p)
I want to understand why this warning generates and why it resolve by declearing double pointer