As we know, in C to dereference a null pointer is undefined behaviour.
It is now, but the PDP-11 was an obsolete architecture before the first standard C was published. At the time when the PDP-11was current hardware, the only thing close to a standard was The C Programming Language by Kernighan and Ritchie (henceforth referred to as K&R).
The null pointer wasn't a formal a concept back then and pointers were generally considered to be interchangeable with
ints although that wasn't always the case (a primary source of pain for portability). A pointer whose value was 0 was considered special and there was a macro
NULL whose definition was something like
((char *) 0). Note that K&R C has no
Dereferencing a null pointer is only designated as undefined behaviour so that the compiler doesn't have add a check to every dereference to make sure the pointer is not null. It's perfectly acceptable for your architecture to have that work as with any other address. In fact, if your program crashes with a
SIGSEGV when you dereference a null pointer, it is not because the compiler put a check in but because your operating system has made it illegal for user space programs to access the location.
So an operating system writer could set up the PDP-11 trap vector table in C as long as he is confident that the compiler will treat address 0 like any other. Since, in early versions of Unix the OS team and the compiler team overlapped, this was obviously not an issue.
So my question is what led some C standard to treat the NULL pointer differently from any other pointer? Did K&R want to target an exotic architecture or something?
No. The C standard came a decade after C and Unix were written. By this time it was obvious that null pointers were causing issues.
OK, so I had a look at my copy of The C Programming Language (first edition) and it turns out that I was wrong. On page 97 we have (in relation to implementing a custom allocator)
C guarantees that no pointer that validly points at data will contain zero, so a return value of zero can be used to signify an abnormal event.
On page 190
A pointer may be compared to an integer but the result is machine dependent unless the integer is the constant 0. A pointer to which 0 has been assigned is guaranteed not to point to any object, and will appear to be equal to 0; in conventional usage, such a pointer is considered to be null.
Setting up an interrupt table for an operating system would not be considered conventional usage.