Arrays always have space allocated to them, so you always know that the memory exists, and how much there is.
> char *pcty;
The compiler reserves storage for the pointer itself (in this respect, its no different from any other type of variable).
However, you still need to assign a value
Both p1 and p3 can be indexed with p to p and all would be well. p2 on the other hand only has p to p to play with.
char arr; // an array
char *p1 = arr; // p1 points to the start of arr
char *p2 = &arr; // p2 points to the middle of arr
char *p3 = malloc ( 20 ); // p3 points to 20 chars in dynamic memory
Like any variable, you need to initialise it before you use it. For an int say, the usual worst that can happen is you get junk printed
Start doing any serious work with the int, and pretty soon it will be clear that not all is well.
printf( "%d\n", random );
Uninitialised pointers are far more dangerous, because the immediate problem isn't apparent (ie, it seems to work)
Assuming that the pointer dereference doesn't actually kill your program, chances are pretty high that it will consistently print 2.
*random = 2;
printf( "%d\n", *random );
Like I said previously, this "seems to work" grace period can last an awful long time (like years) before it bites you.