In C, variables are generally not initialized unless you specifically say so:
int a; // not initialized
int b = 1; // initialized
int arr[10]; // not initialized
int brr[4] = { 1 }; // initialized as { 1, 0, 0, 0 }
void * p; // not initialized
void * q = &a; // initialized
(There are exceptions for variables with static or thread-local storage, which are always zero-initialized.)
It is not allowed to try and get at the value of an uninitialized variable. The only thing you can do with an uninitialized variable is assign to it, which does not access its current value, but only assigns a new value to it. Before initialization or assignment, the current value of a variable is "indeterminate" and you must not attempt to access it. Doing so results in undefined behaviour.
This is true for all variables, but in particular it applies to your pointer variable. It simply has no meaningful value until you assign one.
void * p; // not initialized
if (p) { /*...*/ } // undefined behaviour!
printf("%p\n", p); // undefined behaviour!
p = &a; // now p has a well-defined value
The technical term for the action that is causing undefined behaviour is the so-called "lvalue conversion". That is the moment in which you take a named variable (an "lvalue") and use its content. E.g. C11, 6.3.2.1/2 says:
If the lvalue designates an object of automatic storage duration [...] and that object
is uninitialized (not declared with an initializer and no assignment to it has been
performed prior to use), the behavior is undefined.