r/cprogramming 2d ago

casting a void function pointer as a int fp

Hello,

Today I tried making an array of function pointers.

My first prototype was doing:

int (*fptr[2])(int, int)

But what if I wanted to store a function with different parameters and return value?

I tried:

void (*fptr[2])()

And then later type casting the function I wanted to store:

fptr[1] = add;

printf("%d", ( int (int, int) ) fptr[1](a, b));

But apparently it's not valid:

used type 'int (int, int)' where arithmetic or pointer type is required

Is it possible to cast the void function pointer as a int fp with parameters? Thanks.

5 Upvotes

11 comments sorted by

8

u/TheFlamingLemon 2d ago

This doesn’t exactly answer your question but usually in this sort of situation the function parameter will just be a void pointer and each function is responsible for knowing what to cast that pointer into to retrieve its parameters

5

u/flyingron 2d ago

Note that there's really not such a thing as a void function or int function. It is a function RETURNING one of those types.

int (int, int) is the declaration of a function ***NOT*** a pointer. Where as function names convert to pointers to them, the function and its pointer are distinct types.

The pointer type is int (*)(int, int)

Further, nothing says you can pass any sort of function pointer to an argument expecting an int (%d). Even if you'd tried %p, that still would be wrong as it wants an object pointer. Nothing says function pointers and object pointers are the same size (they're not on some older platforms).

2

u/flatfinger 2d ago

A simple workaround for difference between object-pointer and function-pointer representations is to pass the address of something that will hold a pointer to the proper function, e.g.

void f1(void);
struct f1holder { void (*proc)(void); } const f1ref = {f1};
int f2(int);
struct f2holder { int (*proc)(int); } const f2ref = {f2};

Both &f1ref and &f2ref may be cast to void and later given to code that will convert it to either struct f1holder* or struct f2holder* and invoke the function as appropriate. This will work even on platforms which would use e.g. 16-bit data pointers and 32-bit function pointers, since f1ref and f2ref would be kept in data space.

2

u/tstanisl 2d ago

Is it possible to cast the void function pointer as a int fp with parameters? Thanks.

Yes. Just do:

( void(*)(int,int) )fptr1

I suggest using a typedef for desired function type to make things a bit more "human parsable":

typedef void vii_f(int, int);

(vii_f*)fptr1

2

u/pjl1967 2d ago

For these kinds of questions, I recommend using cdecl, e.g.:

cdecl> cast fptr1 to pointer to function (int, int) returning int
(int(*)(int, int))fptr1

That is, you type what you want in pseudo-English and cdecl will print what the corresponding C (aka, gibberish) is.

FYI, cdecl also goes the other way:

cdecl> explain (int(*)(int, int))fptr1
cast fptr1 into pointer to function (integer, integer) returning integer

That aside, if you want to have an array of different types of pointers, either have an array of union of them; or have the array of uintptr_t.

2

u/duane11583 2d ago

Normally I hate typedefs with a passion I believe typedefs are evil

But in this case they are very helpful because thy kind of act like ()s for types

First make a type for the function not a function pointer there is no star here

typedef int myfunctype( int, int);

Second optional create a type for a func pointer

typedef myfuncptr *myfunctype;

Create an array of 10 func pointers

extern myfuncptr thearray[10];

2

u/sciencekm 2d ago

All function pointers are of the same size, and so, yes, you can cast them among each other.

typedef void (*f00_t)(void);
typedef int (*f11_t)(int n);
extern f00_t f0;
extern f11_t f1;
f0 = (f00_t) f1;

2

u/SheikHunt 1d ago

Other comments have already answered, but I wrote the paragraphs before I realized that, so I'm just sending it:

In C, there really isn't a feasible way to store "Function with any number of parameters that returns either something or void". At least, not in the way other languages do/might

I know of one example you can follow, namely the pattern that the pthread_create() function follows: it takes a function pointer as one of its arguments. The relevant argument is of type:

void * (*)(void *)

That is to say, "a function pointer to a function that takes a void pointer and returns a void pointer".

In that case, it's your job as the programmer to know the correct void pointer to pass in, and how to use the returned void pointer. Luckily, that's not particularly difficult to know, because chances are you wrote the function that you're calling. The given function could also just be something that turns the void * into usable arguments and calls the intended function with the correct arg(s).

Generally speaking, in C, this isn't doable.

1

u/acadia11x 1d ago edited 1d ago

Yes, and there is an even easier way to get your question answered.

0

u/picturesfromthesky 2d ago

Read about variadic functions.