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\"?
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