Search code examples
clanguage-lawyerpointer-arithmeticnull-pointer

Three questions: Is NULL - NULL defined? Is (uintptr_t)NULL - (uintptr_t)NULL defined?


  1. Is NULL - NULL defined.?

  2. Is (char *)NULL - (char *)NULL defined.?

  3. Is (uintptr_t)NULL - (uintptr_t)NULL defined?

I know that it works in all used by me implementations. But how does it look like from the standard point of view? I cant find the clear answer.

Edit: From the dupe I assume that the question one answer is: YES.

What about the second and third questions?


Solution

  • The C Standard documents NULL as being defined as a macro which expands to an implementation-defined null pointer constant

    Depending on the actual definition, the expression NULL - NULL may have a defined value or not. For example:

    • if NULL is defined as #define NULL 0, then NULL - NULL is actually a constant expression of type int with a value of 0.
    • if NULL is defined as #define NULL ((void *)0), the expression NULL is a constraint violation as arithmetic is not defined on void pointers.

    The second question: are (char*)NULL - (char*)NULL or (uintptr_t)NULL - (uintptr_t)NULL defined?. These expressions are no longer constraint violations:

    • since the conversion from void * to an arithmetic type is implementation defined, nothing can be said of the value of (uintptr_t)NULL - (uintptr_t)NULL. It will be 0 on most current systems, but the C Standard does not define it.

    • converting to (char *) is a slightly different matter: the difference of 2 pointers is only defined if they point to the same array, or the position after the last element of the array, an object being considered an array of one element for this discussion. This is not the case in (char *)NULL, which is a null pointer, hence does not point to any array or object.