The code is below.
My question is about the result. I want to understand, why after calling free(p) p->elem turns to \'0\', but the p->str still contains \"hello\"?
Freeing memory doesn't actually clear the pointer or the memory it pointed to (except under specialized circumstances meant to assist in debugging problems like this -- never rely on the behavior though). Using a pointer after freeing the memory it pointed to is invalid, and is undefined behavior. It might as well crash, or cause random values to be printed.
Also, in C you should not cast the return of malloc.