J
Jack Klein
The "special handling" happens in cases like
int* p = 0; // Only legal because of special handling
if (p == 0)... // Only legal because of special handling
Both examples would be illegal if you replace 0 with 1. (double *) 1 is
perfectly legal, with implementation defined behavior.
The Standard does not have an explicit written rule for converting
integers of value 0 that are not null pointer constants, but the
"implementation defined behavior" cannot distinguish between a zero that
is a null pointer constant and a zero that is not a null pointer
constant. The conversion is _only_ based on the value. The C Standard
gives an explicit guarantee (gives an explicit requirement for any
conforming implementation) that in a certain subset of all situations
where a value of 0 is converted, the result will be a null pointer. The
implementation has no choice but converting _all_ zero values to null
pointers.
You are still confused. If you look again at the excerpt from the
standard that defines an "integer constant expression" you will note
that it is an expression with a value known to the compiler at COMPILE
TIME.
When you convert, with a cast, the value of an integer object to a
pointer, the value of that integer object is accessed and evaluated at
RUN TIME.
So the implementation-defined behavior can most certainly distinguish
between a "zero that is a null pointer constant" and a zero that is
not a null pointer constant, whatever that means, presumably the value
of some object that happens to equal 0.
It is probably not even allowable in the RUN TIME operation of
converting an integer value to a pointer with an appropriate cast,
that the implementation could check whether the value evaluates to 0
and if so, convert it to the bit pattern of a null pointer even if its
pattern for a null pointer is not all bits 0.
This is because, assuming an implementations has an integer type large
enough to hold a pointer, then:
-- a conversion integer -> pointer -> integer must end up with the
final integer having the same value as the original, and...
-- a conversion pointer -> integer -> pointer to same type must end up
with the final pointer containing the same address as the original.
So if an implementation had a representation for null pointers that
was not all bits 0, it could either convert integers with the value 0
to that null pointer representation, or integers with the bit pattern
of the null pointer to a null pointer, but not both, otherwise when
converting a null pointer back to an integer type it could not know
whether to generate 0 or the null pointer bit pattern in the
destination integer.