while printing *p should just give out whatever garbage value was randomly assigned to x.
Not sure where you got this impression, but it is based on false assumption or wrong expectation. Standard specifies and creators of the compiler follows that reading value of unintialized variable either directly by using variable name or indirectly, using pointer or reverence leads to Undefined Behaviour. So segmentation fault probably the best outcome you get in this case as it lets you to fix error in your code much easier that getting some random value. But beware you cannot expect of segmentation fault happening either, when you get on UB territory you cannot expect anything particular. It is your job as a developer not doing that.