Search code examples
cpointersstandardsnull-pointer

C: NULL > NULL always false?


Is it guaranteed by the C standard that, given type_t* x = NULL; type_t* y = NULL; we always have x > y evaluating as false? I ask because of the conversation in initial or terminal malloc buffer possible? from which it seems that one should be careful with pointer comparison, and only compare when one is dealing with pointers to elements of the same array, loosely speaking. However, it is convenient to have x > y evaluating as false guaranteed, because I want a struct which is an stack-ish array having fields for the first and post-last elements, and if this array still has 0 elements, it is convenient to set these fields to be NULL, and it is convenient to still allow for for looping over elements of the array, without checking explicitly whether the array has 0 elements or more, so such a comparison is handy...


Solution

  • Surprisingly, in C it appears to cause undefined behavior. Only == and != can work with null pointers. The workaround is to cast the pointers to uintptr_t and compare the results.

    C17 6.5.8 Relational operators /5

    When two pointers are compared, the result depends on the relative locations in the address space of the objects pointed to. If two pointers to object types both point to the same object, or both point one past the last element of the same array object, they compare equal. If the objects pointed to are members of the same aggregate object, pointers to structure members declared later compare greater than pointers to members declared earlier in the structure, and pointers to array elements with larger subscript values compare greater than pointers to elements of the same array with lower subscript values. All pointers to members of the same union object compare equal. If the expression P points to an element of an array object and the expression Q points to the last element of the same array object, the pointer expression Q+1 compares greater than P. In all other cases, the behavior is undefined.

    (bold mine)

    This is unlike C++, where there's a clause explicitly saying that <,<=,>,>= are consistent with ==,!=:

    [expr#rel]/5

    If two operands p and q compare equal ([expr.eq]), p<=q and p>=q both yield true and p<q and p>q both yield false. ...