Schwarz, Konrad wrote:
I think it would be best to stick as closely to the language of the C
standard as possible.
Agreed.
I.e., using ISO/IEC 9899:1999 (E), section 6.3.2.2, paragraph 1 as a
guide:
A pointer to <b>void</b> may be converted to or from a pointer
to any function type.
You would want to allow converting *any* void pointers to function
pointers? I don't think that's necessary. I think it's better to let
it be undefined behaviour, except for void pointers that are converted
pointers to function. That would make it consistent with conversions
from void* to other pointer types in standard C -- they're undefined
unless you have made sure that you're not violating any alignment
requirements. (And since alignment requirements are unspecified, it's
hard to satisfy them other than by ensuring that your void pointer
indeed points to an object of the correct type. Or was returned by
malloc().)
A pointer to any function type may be converted to a pointer to
<b>void</b> and back
again, the result shall compare equal to the original pointer.
Right. It should not be symmetrical.
This just replaces "pointer to any incomplete or object type" with
"pointer to any function type"
in paragraph 1.
I don't think it's a good idea to introduce unusual
restrictions on what
the void* pointer can be converted to. Can I convert it to a "void
const*"? What about a "void *const"? Why would it need to
be undefined
behaviour to convert it to a char*, even though standard C intends to
allow converting any valid void* pointer to char*?
I think these questions are largely answered by paragraph 2 of the
section quoted above:
For any qualifier q, a pointer to a non-q-qualified type may be
converted to a pointer to
the q-qualified version of the type; the values stored in the
original and converted pointers
shall compare equal.
I don't think it's clear that that paragraph applies. Keep in mind that
we're talking about programs that have invoked undefined behaviour
according to the C standard (by converting a function pointer to a void
pointer). This new kind of void* values that POSIX is trying to
introduce does not exist in standard C; if POSIX specifically says that
the behaviour is undefined if such a value is converted to a pointer
to an object or an incomplete type, I would tend to interpret that as
overriding what C says about conversions of normal pointers -- not the
other way around.
Also, a few details are missing from the wording in question:
* Do these conversion work with null pointers? Are they
guaranteed to
turn null pointers into null pointers? (If not, then one
needs to test
the result of dlsym() before converting it to a function
pointer, rather
than after.)
This is answered by paragraphs 3 and 4:
...
Conversion of a null pointer to another pointer type yields a
null pointer of that type.
OK, but still, it's not obvious to me that this necessarily applies to
conversions that have undefined behaviour in standard C.
* Is it possible for the converted void* pointer to compare
equal to the
address to some object? (It can happen on hardware with separate
address spaces for code and data -- does POSIX want to support such
hardware?)
I think POSIX should leave these areas unspecified---what does
specifying these details gain POSIX? Thus add to the above:
Normally a void* pointer can be compared to another void* pointer; if
you make it undefined behaviour for some valid pointers, you'll be
introducing an inconsistency that people will tend to forget about. My
feeling is that it would be better to allow comparing but discourage it
by saying that the result is unspecified.
(I would still prefer to say that it may accidentally happen to compare
equal to some object pointers, because that's consistent with how C says
that a pointer to object may accidentally compare equal to a pointer
past the end of some unrelated array. But I could live with simply
"unspecified", even though I don't like the idea of it returning any
value other than 0 or 1, or the idea that it might return different
values when you compare the same two pointers twice.)
If a pointer to any function type, converted to a pointer to
<b>void</b>,
is used for any purpose other than conversion back to a pointer
to a
function or comparison with a null pointer, the behavior is
undefined.
Comparison with a null pointer, or specifically with a null pointer
constant?
Can't it be used in an assignment? In a compound literal? Passed to a
function? Returned from a function? Used to initialize a variable?
Converted to void? To _Bool? To another function pointer stored in a
void*?
In general, it would be good idea to consult Clive D.W. Feather on this.
Agreed.
|