Reputation: 7604
If I have a prototype that is declared as:
void foo(int (*fi)(void *, void *))
And I call the function with something like this:
foo(int (*)(void*, void*)(bool_expr ? func1 : func2));
Where func1 and func2 are defined as follows:
int func1(char *s1, char *s2);
int func2(int *i1, int *i2);
Is the function call casting one of the functions (func1 ^ func2) to the type of the function required by foo? Could I also make the prototype for foo look like:
void foo(int (*)(void *, void *))
Upvotes: 3
Views: 2695
Reputation: 183564
In GCC, this expression:
bool_expr ? func1 : func2
gives this warning:
warning: pointer type mismatch in conditional expression
even if you don't turn on special warnings.
What's more, GCC resolves this pointer-type mismatch by casting both expressions to void *
; so then, when you try to cast it back (either explicitly, with (int (*)(void*, void*))
, or implicitly, by passing it to foo
), it gives this warning:
warning: ISO C forbids conversion of object pointer to function pointer type
if you enable pedantry. (The reason that ISO C forbids this is that a function pointer does not have to be implemented, internally, as a pointer to a memory location, so it may not have the same size and whatnot as a regular "object" pointer.)
That said, this:
foo((bool_expr ? (int (*)(void*, void*))func1 : (int (*)(void*, void*))func2));
should be relatively safe, provided that foo
is passing valid char
pointers to func1
or valid int
pointers to func2
.
And I would guess that, on a system where function pointers are truly incompatible with void *
, a compiler wouldn't resolve the mismatch bool_expr ? func1 : func2
in favor of void *
(though I haven't consulted the spec on this).
Upvotes: 2
Reputation: 122011
As commented the code as posted did not compile.
FWIW, this compiles and executes as you would expect with VC2010:
int func1(char *s1, char *s2) { printf("func1\n"); return 0; }
int func2(int *i1, int *i2) { printf("func2\n"); return 0; }
void foo(int (*)(void *, void *));
int main(int argc, char** argv)
{
foo(2 == argc ? (int(*)(void*,void*))func1 :
(int(*)(void*,void*))func2);
return 0;
}
void foo(int (*a)(void *, void *))
{
a((void*)0, (void*)0);
}
Upvotes: 1
Reputation: 727047
According to C specification, casting function pointers results in unspecified behavior, but many compilers (e.g. gcc) do what you expect them to do, because function pointer is just an address in memory. Just to be safe, I would re-declare func1 and func2 to take void*, and then cast these pointers to char* and int* as required.
Upvotes: 2