Following discussion from this question about null pointers in C and C++, I\'d like to have the ending question separated here.
If it can be inferred from C and C++ stan
does it imply that these languages require that a special value in the address space is dead, meaning that it's unusable except for the role of representing
nullptr
?
No.
The compiler needs a special value to represent a null pointer, and must take care that it does not place any object or function at that address, because all pointers to objects and functions are required to compare unequal to the null pointer. The standard library must take similar precautions in its implementation of malloc
and friends.
However, if there is something at that address already, something that no strictly conforming program can access, then an implementation is allowed to support dereferencing the null pointer to access it. Dereferencing the null pointer is undefined in standard C, so an implementation can make it do anything it likes, including the obvious.
Both the C and the C++ standards understand the concept of the as-if rule, which basically means that if to valid input, an implementation is indistinguishable from one that conforms to the standard, then it does conform to the standard. The C standard uses a trivial example:
5.1.2.3 Program execution
10 EXAMPLE 2 In executing the fragment
char c1, c2; /* ... */ c1 = c1 + c2;
the "integer promotions" require that the abstract machine promote the value of each variable to
int
size and then add the twoint
s and truncate the sum. Provided the addition of twochar
s can be done without overflow, or with overflow wrapping silently to produce the correct result, the actual execution need only produce the same result, possibly omitting the promotions.
Now, if c1
and c2
's values come from registers, and it's possible to force values outside of char
's range into those registers (e.g. by inline assembly), then the fact that the implementation optimises away the integer promotions might be observable. However, since the only way to observe it is through undefined behaviour or implementation extensions, there is no way for any standard code to be affected by this, and an implementation is allowed to do it.
This is the same logic that applies to getting useful results when dereferencing null pointers: there are only two ways to see, from code, that there is something meaningful at that particular address: getting a null pointer from an evaluation that is guaranteed to produce a pointer to an object, or by just trying it. The former is what I mentioned the compiler and standard library must take care of. The latter is not something that can affect a valid standard program.
A well-known example is the interrupt vector table on DOS implementations, which resides at address zero. It is typically accessed simply by dereferencing a null pointer. The C and C++ standards don't, shouldn't and cannot cover access to the interrupt vector table. They do not define such behaviour, but they do not restrict access to it either. Implementations should be and are allowed to provide extensions to access it.