C 2018 6.3.2.3 4 says:
Conversion of a null pointer to another pointer type yields a null pointer of that type. Any two null pointers shall compare equal.
This paragraph, unlike paragraph 7, does not limit the conversions to pointers to object types or pointers to function types. Therefore, if a null pointer of some pointer-to-function type is converted to void *
, the result is a null pointer, and then applying !
to it yields 1.
Establishing the converse, that if applying !
to a pointer yields 1, it necessarily arose from a null pointer, it more difficult. We could imagine some non-null function pointer that, when converted to void *
, yields a null pointer. Considering the intent of POSIX to allow function pointers to be temporarily stored in void *
, we can conclude that converting a pointer to a function to void *
should never result in a null pointer.
Could the bit pattern for a NULL void* data-pointer ever equate to a non-NULL function-pointer value?
The C standard does not discuss the bit patterns used to represent pointers. The semantics are established in terms of the values.
Would any sane implementation do this?
Certainly bare-metal boot code on some hardware might put executable instructions at address zero and call a function there for some reason and might also use address zero as a null pointer. It will simply be designed not to depend on that function at address zero not being tested for being a null pointer.
Outside of such special situations, i.e., for all practical purposes, this is not done. If some software decides it needs a special representation for a null pointer, it will set aside some address for that and not use that address for any ordinary function or object.