As others have mentioned, saving the address of a local variable then attempting to dereference that address after the function returns is undefined behavior.
What that means is that your program could crash, it could exhibit strange behavior, or it could appear to work properly. This behavior does not need to be consistent from one compiler to the next for the same code or in the presence of a seeming unrelated change.
That being said, many compilers typically won't modify the portion of the stack used by a function after it returns. It's extra work that usually isn't needed. So immediately after fun
returns, the local variables it has still contain their old values.
On the call to printf, the pointer p2
is dereferenced before printf is called. Since no other functions were called prior to this happening, the value of a from the last call to fun
has not yet been overwritten. So you read the old value.
If you were to call some other function before calling printf
, the memory location previously occupied by q will get overwritten, so that you'll likely see some other value.
To reiterate however, this is undefined behavior. Not all compilers are required to behave in this fashion. For example, in a high security environment a compiler might clear out stack memory after a function returns so that sensitive data used by that function cannot be recovered.