In C99, equality == does not seem ever to be undefined. It can produce 1 by accident if you apply it to invalid addresses (for instance &x + 1 == &y may be true by accident). It does not produce undefined behavior. Many, but not all, invalid addresses are undefined to compute/use according to the standard, so that in p == &x with p a dangling pointer, or in &x + 2 == &y, the invalid address causes the undefined behavior, not ==.
On the other hand, >= and other comparisons are undefined when applied to pointers that do not point within the same object. That includes testing q >= NULL where q is a valid pointer. This test is the subject of my question.
I work on a static analyzer for low-level embedded code. It is normal for this kind of code to do things outside what the standard allows. As an example, an array of pointers may, in this kind of code, be initialized with memset(...,0,...), although the standard does not specify that NULL and 0 must have the same representation. In order to be useful, the analyzer must accept this kind of thing and interpret them the way the programmer expects. Warning the programmer would be perceived as a false positive.
So the analyzer is already assuming that NULL and 0 have the same representation (you are supposed to check your compiler against the analyzer to make sure they agree on this kind of assumptions). I am noticing that some programs compare valid pointers against NULL with >= (this library is an example). This works as intended as long as NULL is represented as 0 and pointer comparison is compiled as an unsigned integer comparison.
I only wish the analyzer to warn about this if, perhaps because of some agressive optimization, it may be compiled into something different from what the programmer meant on conventional platforms. Hence my question: is there any example of a program not evaluating q >= NULL as 1, on a platform where NULL is represented as 0?
NOTE: this question is not about using 0 in a pointer context to get a null pointer. The assumption about the representation of NULL is a real assumption, because there is no conversion in the memset() example.
There are definitely pointers that when you reinterpret them as a signed integer of pointer size will have negative sign.
In particular all kernel memory on Win32, and if you use “large address aware” then even 1GB of userspace since you get 3GB of userspace.
I don’t know the details of c pointer arithmetic, but I suspect that these might compare as <0 in some compilers.