That's simply not true. There is the rule, that NULL must be equal to (void *)0. I had also several discussions about that topic, but it's part of at least C99 and C11.
An integer constant expression with the value 0, or
such an expression cast to type void *, is called a
null pointer constant. If a null pointer constant
is converted to a pointer type, the resulting pointer,
called a null pointer, is guaranteed to compare unequal
to a pointer to any object or function.
Conversion of a null pointer to another pointer type
yields a null pointer of that type. Any two null pointers
shall compare equal.
If you do this: int pv = 0;
char * p = (char *)pv;
you are not guaranteed to have p set to a null pointer, because the zero you are casting and assigning is not an integer constant zero. The behavior is implementation-defined, as is going the other way. Section 6.3.2.3 paragraphs 5 and 6: An integer may be converted to any pointer type. Except
as previously specified, the result is implementation-defined,
might not be correctly aligned, might not point to an entity
of the referenced type, and might be a trap representation.
Any pointer type may be converted to an integer type. Except
as previously specified, the result is implementation-defined.
If the result cannot be represented in the integer type, the
behavior is undefined. The result need not be in the range of
values of any integer type. char *p1 = 0;
int pv = (intptr_t)p1;
char *p2 = (char *)pv;
I.e. NULL must round-trip through intptr_t.