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 two int
s and truncate the sum. Provided the addition of two char
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.
nullptr
doesn't even exist in C, and the definition ofNULL
differs between the two languages. Furthermore, there is a ton of wording difference between the two around this topic. If the answers happen to be the same then great, but lumping together two distinct questions about two distinct languages just on the offchance of that is wrong. – MercantileNULL
has a somewhat significant difference. In C,((void*)0)
is a valid definition forNULL
; in C++, it's not. That's not relevant to what you're asking, but it illustrates that you shouldn't assume C and C++ are identical in some way. – Exorable