On 01/19/2012 04:45 PM, � wrote:
> On 19.01.2012 19:45, Shao Miller wrote:
>
>> I have a limited use case for empty parentheses, that does come in handy:
>
> Unfortunately, your use case is useless.
>
> [...]
>> int main(void) {
>> sometype_f * fptr;
>> spiffy_f * spiffy_ptr;
>>
>> /* 'fptr' is kind of like a 'void *' */
>> spiffy_ptr = fptr = my_nifty;
>
> Non-prototype declarations don't make any difference with that. It is
> already allowed to store any arbitrary function pointer value in any
> arbitrary function pointer typed object, regardless of the functions
> pointer types' signatures. You can completely skip your non-prototyped
> sometype_f type and fptr object, and just write
>
> spiffy_ptr= my_nifty;
I can't tell from the code fragment you've written what the relevant
function types are, I've got the OP killfiled. However, depending upon
what they were, there could be a real (though debatably useful)
advantage to using fptr as an intermediate step.
Your suggested replacement would a constraint violation unless spiffy_f
is compatible with my_nifty 6.5.16l1; an explicit conversion is required
to bypass that constraint. If they aren't compatible, but sometype_f is
compatible with both, then using fptr as an intermediate step makes the
relevant conversions occur implicitly. For instance, if sometype_f is
declared as
typedef int sometype_f();
then sometype_f* is compatible with any pointer to a function type that
returns an 'int' and accepts a fixed number of arguments. Personally, I
think that using a cast to make the conversion explicit would be a
better way to handle this.
> And anyway, no, there is no such thing as a generic function pointer,
> nor a particular need for one: every function pointer is already
> generic. Just about the only thing you're allowed to do with a
> function pointer value stored in a wrong-type function pointer object is
> to cast it back to the original type, anyway, so casting function
> pointers is pretty pointless exercise to begin with.
That's not quite true; a pointer to a function returning a given type
with an unspecified number of parameters (which can only be done using
an unprototyped function declaration) can be used to call any function
with the same return type that is defined as accepting a fixed number of
parameters, so long as the actual call using that pointer involves
arguments whose number and promoted types match the function's
definition. Example:
#include <stdio.h>
enum type {VOID, INT, PCHAR, ETC};
int call_func(int (*func)(), enum type t)
{
switch(t)
{
case VOID: return func();
case INT: return func(1);
case PCHAR: return func("two");
default:
fprintf(stderr, "Invalid type in call_func():%d\n", t);
return -1;
}
}
All of the following are legal calls; none require a cast:
call_func(getchar, VOID);
call_func(putchar, INT);
call_func(remove, PCHAR);
The fact that this works only for functions with the same return type,
and can't work for variadic functions makes such function pointers less
generic than void* pointers are for object types; but the convenience
factor is the same.
--
James Kuyper