There are two problems with this code.
First, printf expects its first argument to be a format string, and the type of the argument is assumed to be const char * (it's a pointer to the first character in a zero-terminated string).  Since the object p has type int *, the expression *p has type int, so it's the wrong type, and the value of *p isn't a valid address of a string, because...  
You've initialized p to NULL.  NULL is an invalid pointer value that's guaranteed to compare unequal to any valid pointer value (it's a well-defined "nowhere" value).  When you write *p, you're saying, "I want the value of the integer object p points to."  Since p points "nowhere", the behavior of the operation is undefined, and one possible result of undefined behavior is a segfault.  
So...
If you want to print the value of the integer object that p points to, you would write something like
printf( "%d\n", *p );
but only after you do a sanity check on p to make sure it isn't NULL:
if ( p ) // or p != NULL
  printf( "%d\n", *p );
Valid pointer values are obtained by one of the following methods:
- Using the unary &operator on an lvalue (an expression that refers to an object in memory such that the object may be read or updated):
     p = &x;       // x is an integer object
    p = &a[i];    // a is an array of integer, so a[i] is an integer object
    p = &foo.bar; // foo is a struct with an int member named bar, so foo.bar is an integer object
 etc.
- Calling one of malloc,calloc, orrealloc:    p = malloc( sizeof *p );
 
- Using an array expression in most circumstances.  Unless it is the operand of the sizeofor unary&operators, or is a string literal being used to intialize a character array in a declaration, an expression of type "N-element array ofT" will be converted ("decay") to an expression of type "pointer toT", and the value of the expression will be the address of the first element of the array.  In the case ofprintf, when we write    printf( "this is a test\n" );
 the type of the string literal"this is a test\n"is converted from type "16-element array ofchar" to "pointer tochar", and its value is the address of the first character in the string - that address value is what actually gets passed toprintf.