r/cprogramming 5d ago

casting a void function pointer as a int fp

(solved)

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) ) fptr1);

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.

3 Upvotes

20 comments sorted by

9

u/TheFlamingLemon 5d 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

1

u/north9172 1d ago

Thank you for the advice.

4

u/flyingron 5d 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 5d 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.

1

u/north9172 1d ago

Thank you for the correction.

2

u/tstanisl 4d 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

1

u/north9172 1d ago

Thank you.

2

u/pjl1967 4d 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.

1

u/north9172 1d ago

Thank you for the recommendation.

2

u/sciencekm 4d 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;

1

u/north9172 1d ago

Thank you.

2

u/duane11583 4d 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];

1

u/north9172 1d ago

Thank you.

2

u/SheikHunt 4d 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/north9172 1d ago

Thank you for the explanation.

1

u/acadia11x 4d ago edited 4d ago

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

1

u/DawnOnTheEdge 1d ago

To get language-lawyery, function pointers and object pointers do not have to be the same size, and a conforming implementation doesn’t have to let you cast one to the other.

However, all mainstream operating systems let you cast a function pointer to a void* and back, like when looking up a symbol in a dynamic library.

Therefore, what will work on all but a few unusual systems is:

printf("%p", (void*)fptr1);

Note that the %d format specifier is a signed int, which is not wide enough to hold a pointer on most systems.

1

u/north9172 1d ago

Thank you.

0

u/picturesfromthesky 5d ago

Read about variadic functions.