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.
First, never do that in actual code. Your code works now only because the memory wasn't claimed by other allocations yet, and there's still a "ghost" of the old allocated struct.
On the actual question, your p->str pointer is pointing to a constant literal, i.e. a piece of text which is "hardcoded" in the application data. Hence, the pointer to it will be valid throughout application lifetime - here's a "more valid" example:
p_node p;
p=(p_node)malloc(LEN);
p->elem=99;
p->str="hello";
char* pstr = p->str;
free(p);
printf("the pstr :%s\n",pstr); // still outputs "hello", because pstr would be just a pointer to "hardcoded" data