POSIX requires (I think) that function pointers can be stored in a variable of type void* and/or passed to functions expecting a void* argument, even though this is strictly non-standard.
My question is this: if I test such a variable/argument for NULL
-ness, if (!(variable or argument))
say, and the result is true
, does that necessarily mean that the function-pointer is NULL
? Could the bit pattern for a NULL void* data-pointer ever equate to a non-NULL function-pointer value? Would any sane implementation do this? Do any common implementations do this?
CodePudding user response:
This C11 Draft Standard suggests that, while not part of the core standard, casting function pointers to object pointers (for purposes of testing, as in your NULL
-check) falls under the category of "Common Extensions" (Annex J.5):
J.5.7 Function pointer casts
1 A pointer to an object or to
void
may be cast to a pointer to a function, allowing data to be invoked as a function (6.5.4).2 A pointer to a function may be cast to a pointer to an object or to
void
, allowing a function to be inspected or modified (for example, by a debugger) (6.5.4)
CodePudding user response:
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.