According to this Berkeley course and this Stanford course, allocating an int to a pointer like so should crash my program:
First off let's get your terminology correct. You are not "allocating an int
to a pointer". Allocation is the creation of a storage location. An int
is a value. A pointer is a value. A pointer may be dereferenced. The result of dereferencing a valid pointer is to produce a storage location. The result of dereferencing an invalid pointer is undefined, and can literally do anything. A value may be assigned to a storage location.
So you have:
int *p;
You have allocated a (short-lived) storage location called p
. The value of that storage location is a pointer. Since you did not initialize it to a valid pointer, its value is either a valid pointer or an invalid pointer; which is it? That's up to your compiler to decide. It could always be invalid. It could always be valid. Or it could be left up to chance.
Then you have:
*p = 5;
You dereferenced a pointer to produce a storage location, then you stuck 5 in that storage location. If it was a valid pointer, congratulations, you stuck 5 into a valid storage location. If it was an invalid pointer then you've got undefined behaviour; again, anything could happen.
printf("p is %d\n", *p); // 5!
Apparantly you got lucky and it was a valid storage location this time.
According to this Berkeley course and this Stanford course [this] should crash my program:
Then those courses are wrong, or you are misquoting them or misunderstanding them. That program is permitted to do anything whatsoever. It is permitted to send an email inviting the president of Iran to your movie night, it is permitted to print anything whatsoever, it is permitted to crash. It is not required to do anything, because "permitted to do anything" and "required to do something" are opposites.