2 points:
-
only the constant value 0 in the source code is the null pointer – the compiler implementation can use whatever value it wants or needs in the running code. Some platforms have a special pointer value that’s ‘invalid’ that the implementation might use as the null pointer. The C FAQ has a question, “Seriously, have any actual machines really used nonzero null pointers, or different representations for pointers to different types?”, that points out several platforms that used this property of 0 being the null pointer in C source while represented differently at runtime. The C++ standard has a note that makes clear that converting “an integral constant expression with value zero always yields a null pointer, but converting other expressions that happen to have value zero need not yield a null pointer”.
-
a negative value might be just as usable by the platform as an address – the C standard simply had to chose something to use to indicate a null pointer, and zero was chosen. I’m honestly not sure if other sentinel values were considered.
The only requirements for a null pointer are:
- it’s guaranteed to compare unequal to a pointer to an actual object
- any two null pointers will compare equal (C++ refines this such that this only needs to hold for pointers to the same type)