4

I have an array which looks like this:

void* functions[]; // pointer to functions, each function returns an int and has int parameters A and B

I would like to cast this into the following:

int (*F)(int a, int b) = ((CAST HERE) functions)[0];
int result = F(a, b);

I have already tried "(int (*)(int, int))" as the cast but the compiler complained I am trying to use the function pointer as an array.

4
  • The compiler is right. Check your parentheses. Commented Sep 24, 2017 at 6:03
  • 1
    May try: int (*F)(int, int) = (int (*)(int,int))functions[0]; Commented Sep 24, 2017 at 6:12
  • 1
    Use a typedef... Commented Sep 24, 2017 at 6:23
  • Unfortunately I cannot @M.M Commented Sep 24, 2017 at 7:12

3 Answers 3

4

It will help to use a typedef for the function type:

typedef int F_type(int, int);

Then you can write:

F_type *F = (F_type *)(functions[0]);

It would be undefined behaviour (strict aliasing violation) to try and cast functions to something else before using the index operator.

Note that it is not supported by Standard C to convert void * to be function pointers. If possible, make the array be function pointers in the first place:

F_type *functions[] = { &func1, &func2 };

NB. Some people prefer using a typedef for the function pointer type, instead of the function type. I think it makes for more readable code to avoid pointer typedefs, but I mention this so you can make sense of other suggestions.

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

8 Comments

Good answer, but I am afraid OP doesn't want a typedef.
@gsamaras sure. I downvoted your answer as it will cause undefined behaviour . Also what is your basis for claiming OP doesn't want a typedef?
Oh really? Hmm I am not sure why, could you please explain? Ah I might be wrong, since nm told OP about the typedef, then the OP answered I cannot do that, but he was answering to mm.. Sorry!
@gsamaras I mentioned in my answer... it aliases void * as a different type, which is a strict aliasing violation (unrelated types can not be aliased in general)
I appreciate this safer approach @M.M, thank you very much for it, but the problem is that I was using a third party library for this and wanted to keep it simple. So yes I was avoiding typedefs.
|
2

Casting with (int (**)(int, int)) might seem to do the trick now, but it invokes Undefined Behavior!

Converting void* to function pointer is not Standard C.

Note that aliasing void* to a different type; a strict aliasing violation. Read more in What is the effect of casting a function pointer void?

Please consider using an array of function pointers from the start.

1 Comment

Aliasing and conversion are different things. Aliasing incompatible types violates the strict aliasing rule, it does not invoke a conversion. For a more stark example, compare double d[2] = {5.0,6.0}; int x = d[0]; (conversion) versus int y = ((int *)&d)[0]; (aliasing)
0

function is an array of pointers to data of type void. You want to cast it to a pointer to pointers of type int (*)(int, int) which would be int (**)(int, int), so the following works:

int (*F)(int, int) = ((int (**)(int, int)) functions)[0];

As pointed out by @M.M, the above will result in undefined behaviour. You might want to read this post and this for more on that.


Ideally, you would do something like this:

// Array of 2 pointers to functions that return int and takes 2 ints
int (*functions[2])(int, int) = {&foo, &bar};

// a pointer to function
int (*F)(int, int) = functions[0];
int r = F(3, 4);

7 Comments

This causes undefined behaviour
I tested this and it seemed to work for my application, thank you!
@Jas - Undefined behavior doesn't mean "not work". It may "seem to work" for a long time, until it breaks for no apparent reason upon moving to a new platform. By then you'd have forgotten this post and had to do overtime to figure out where you messed up.
Hmm I see, but isn't a typedef just an alias? Wouldn't the compiler treat both approaches in the same manner
@Jas - You don't have to use a typedef to follow M.M's approach. The key point is that the indexing must happen before the cast. F = (int(*)(int, int))(functions[0]);. But then again, an array of void* that holds function pointers is not something the C language standard supports.
|

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.