On 10/10/2017 10:30 AM, Joseph Myers wrote:
On Tue, 10 Oct 2017, Martin Sebor wrote:

I know of pre-existing code-bases where a type-cast to type:
void (*) (void);

.. is already used as a generic function pointer: libffi and
libgo, I would not want to break these.

Why not fix them instead?  They're a part of GCC so it should
be straightforward.  It doesn't seem like a good tradeoff to

Sometimes an interface needs to store an arbitrary function type for which
an ABI-compliant call ends up being constructed at runtime from assembly
language (or from non-C, in general).  That's the sort of thing libffi
does - so it inherently needs to be able to take pointers to arbitrary
function types, which thus need to be converted to a generic function
type, and the de facto generic function pointer type in C is void (*)
(void).  (C11 6.11.6 says "The use of function declarators with empty
parentheses (not prototype-format parameter type declarators) is an
obsolescent feature.", so void (*) () is best avoided.)  Likewise
interfaces such as dlsym (which happens to return void * along with a
special case in POSIX requiring conversions between void * and function
pointers to work, but void (*) (void) is the natural type for such
interfaces to use).

I agree that unprototyped functions are best avoided in cases
where type checking is needed (i.e., in most use cases).  I also
agree that "generic function pointers") are not uncommon and are
worth accommodating.

But I don't think that adopting an inferior mechanism for it when
a better alternative exists is helpful.

Calling a function that takes arguments via a void (*)(void)
is undefined not just on paper but also in practice, so the
resulting pointer from such a cast is unusable except to convert
to a compatible pointer.

On the other hand, it is well-defined or safe to use a void (*)()
to call essentially any function, so it is a superior choice for
this use case.  Even if the pointer is only used for storage and
never to call a function, the syntax is elegant and the intent
clear.

Martin

PS It would be useful if modern C provided a clean mechanism to
support generic function pointers rather that forcing users leery
of relying on obsolescent features to invent workarounds.  One
alternative is to unobsolesce unprototyped functions for this
use case (i.e., for pointers to functions).  Another might be to
invent some other syntax (e.g., void (*)(...) since it's accepted
in C++).  But using void(*)(void) feels like a hack to me.

Reply via email to