Matthew Hoggan
Matthew Hoggan

Reputation: 7604

Casting a Function Pointer

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

Answers (3)

ruakh
ruakh

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

hmjd
hmjd

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

Sergey Kalinichenko
Sergey Kalinichenko

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

Related Questions