This question might be too bad but I can take risk to post this question here to address my confusion.
Actually my question is that we can only assign address to poi
barak manos already pointed it out in his comment:
If you want to set a pointer to a literal value, you need to cast the literal value to the corresponding pointer type first.
NULL could just as well be defined as (void *) 0... which is implicitly convertible to any pointer type.
In either case, you end up with a pointer pointing to a literal address.
In no case, however, does your pointer point to memory containing a literal 4, though. This is, to my knowledge, not possible without assigning that literal value to an int first:
int i = 4;
int * p = &i;