3

I've seen some examples of array of function-pointers (here, for example)

In the examples I've seen the array holds functions that have a return value of the same type (all int's, or all void's for example).

But I'm wondering can you have an array that holds function-pointers of different types?

The next code won't compile:

#include <stdio.h>

void Empty_Funcion()
{
    ;
}
int funcAdd(int a, int b){
    return a+b;
}

int main()
{
    int ret = 0;

    void *array[5] = {&Empty_Funcion, &funcAdd, &Empty_Funcion, &funcAdd, &Empty_Funcion};

    ret = (*array[1])(5,7);

    printf("%d\n", ret);

    return 0;
}

It says the problem is with the assignment ret =... "void value not ignored as it ought to be".

1
  • note: converting a function pointer to and from void * is not supported by Standard C. Compilers may offer it as an extension. In Standard C you can cast to void(*)() instead, and use array type void (*array[5])() = ... Commented Sep 11, 2016 at 22:34

3 Answers 3

2

You can do it like this:

ret = ( ( int (*)(int,int) ) array[1] )(5,7);

You need to cast to pointer to function type with the correct signature.

Sign up to request clarification or add additional context in comments.

6 Comments

Thanks! And I just tried your code with typedef to make the casting a bit more easier to read, and it also works ( i.e. typedef int (*ptrInt)(int, int); and then the casting is just (ptrInt)array[1]... )
also noticed I have to change my array declaration from (*array[5])() = ... to void *array[5] = ...
@jamesdlin why not?
Sorry, ignore my previous comment. Casting a pointer-to-function to a different type of pointer-to-function and back is legal by 6.3.2.3/8 in the C99 standard.
@DavidRefaeli Actually, the way you've updated your question now makes this not strictly legal. See the update to my answer.
|
2

But I'm wondering can you have an array that holds function-pointers of different types?

As noted in Anatoly's answer, your code doesn't work because your array intends to declare contain pointers-to-functions that return void, but then you try invoking it as a pointer-to-function that returns int. These are incompatible types, so an explicit cast is required. And, as noted in section 6.3.2.3/8 of the ISO C99 standard, casting a function pointer to a different function pointer type and back again is permitted:

A pointer to a function of one type may be converted to a pointer to a function of another type and back again; the result shall compare equal to the original pointer. If a converted pointer is used to call a function whose type is not compatible with the pointed-to type, the behavior is undefined.

That said, I don't see any point to doing this. The function pointer cast is a static cast (a cast known to the compiler) and not a dynamic cast, so you must manually keep track of which elements in your array are of type void (*)() and which are of type int (*)(int, int). It'd instead be simpler to have a separate array for each function pointer type and avoid casting altogether. Doing so would be less error-prone since you would not risk invoking a function pointer as the wrong type (which would be undefined behavior).


Update: You've changed your question so that array is now an array of void* pointers. Note that although normal pointers may be freely cast to and from void*, this is not true for function pointers (although it is considered to be a common extension in many implementations).

2 Comments

Can you give an example of how to initialize the array of function-pointers? Because what I've tried so far failed: 1) void (*array[2])(void) = {ptrAdd, ptrEmpty}; 2) void (*array[2])(int, int) = {ptrAdd, ptrEmpty}; 3) void (*array[2])(int) = {ptrAdd, ptrEmpty}; The compiler keeps throwing error because of incompatible pointer type. I had to resort to an array of void-pointers...
@DavidRefaeli The whole point of your question is that you're trying to force incompatible function pointers into a single array. Consequently, you'll need explicit casts to the expected function pointer type (e.g. (void (*)(void)) ptrAdd) when assigning and to cast back to the original type on use. But as I (and M.M) already explained, this is a lot of extra work for zero gain. You'd be much better off declaring separate arrays and avoiding casts.
0

Your array is not declared as an array of function pointers, it is declared as an array of pointers to void.

To declare the array as an array of function pointers you can do:

int (*)(int,int) array[5] = ...

or for clarity:

typedef int (*my_function_pointer_type)(int,int);

my_function_pointer_type array[5] = ... 

In theory, you cannot call a function which returns void and expect it to return something. This is against the C standard. In practice, if you do this you most likely get an unpredictable value, but in some cases (such as trying to return a structure) with some ABIs you can get a crash.

The best way is to match the type of your "dummy" function to the type of other functions being put into the array.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.