Is this undefined? Probably. Absent compiler optimizations, it won't cause a crash on any system you're ever likely to encounter because it's not actually dereferencing the pointer, but some versions of gcc have caused security issues in Linux by optimising away NULL checks like this.
It is not always defined. It's defined to take an address to a pointer with an offset within the object's space plus one. Subtracting two pointers to distinct objects is undefined. This is to allow for segmented memory architectures. It's also to allow implementation of garbage collectors by the compiler