C generic Parameter into Function pointer - c

Is it possible in C(not C++) to have a fuction pointer that takes a generic value(not a pointer), with -pedantic and -wall -werror flags set.
Note: I can't change the parameter Type. The code has to support uint8_t, uint16_t, etc... types as the parameters
Goal: to solve the problem with code.
Question
Is there a way to typecast a uint8_t(and/or uint16_t) parameter to a void*(Approach1)?
specifically to pass a non-pointer type value to a void* value.
Is there a way to setup a Generic Type that will work with all the different values(Approach 2)?
Last resort
Is there a way to set a specific compiler Exception in the code?(this question has been answer)
Approach 1(causes a invalid conversion from uint8_t to void*)
typedef struct
{
void (*set_func)(void*);
} SetFunction;
void setValue(uint8_t byteValue)//Not a pointer parameter
{
byteValue++;
}
void setShortValue(uint16_t byteValue)//Not a pointer parameter
{
byteValue++;
}
int main()
{
uint8_t a = 123;
uint16_t b = 321;
SetFunction pointerFuncion;
SetFunction pointerFuncionShort;
//Typecast the setValue to appease compiler warning
pointerFunction.set_func = (void(*)(void*))&setValue;
pointerFuncionShort.set_func = (void(*)(void*))&setShortValue;
//use the function pointer with non-pointer parameter
// Compile ERROR thrown invalid conversion from uint8_t to void*
pointerFunction.set_func(a);
pointerFuncionShort.set_func(b);
}
Aprroach 2(causes a Too Many Parameters Compile Error)
typedef struct
{
void (*set_func)();//Blank parameter to allow multiple args
} SetFunction;
void setValue(uint8_t byteValue)//Not a pointer parameter
{
byteValue++;
}
void setShortValue(uint16_t byteValue)//Not a pointer parameter
{
byteValue++;
}
int main()
{
uint8_t a = 123;
uint16_t b = 321;
SetFunction pointerFuncion;
SetFunction pointerFuncionShort;
//Typecast the setValue to appease compiler warning
pointerFunction.set_func = (void(*)())&setValue;
pointerFuncionShort.set_func = (void(*)())&setShortValue;
//use the function pointer with non-pointer parameter
pointerFunction.set_func(a);// Compile ERROR thrown "Too many Args"
pointerFuncionShort.set_func(b);// Compile ERROR thrown "Too many Args"
}
UPDATE
To add clarity to the problem.
I have 100's of functions with 1 parameter.
The 1 parameter of the functions are different types.
I can't change any of the functions, but I want to have 1 function pointer type(or more based on type) to any of the functions.
I can change any of the types associated with the function pointer and the type to the function pointer, but not what it is pointing too.

No, it is not.
Simple answer: The called function does not know how to even fetch the argument.
Details: The function code is already fixed when it is called (executed). So it contains code to access the argument, which depends on the type of the arguemtn (e.g. for an uint32_t, a 32 bit load/soter is required, for an uint8_t an 8 bit load/store). So it cannot handle even the value fetch properly.
Different from C++ and higher languages like Python, C does not have a concept of run-time type identification built-in.
However, you can pass a union to the function and handle each variant in the function seperately. That would generate all possible accesses. However, you have to specify which actual type is being passed. This is normally done by a second argument which specifies the actual type.
That union could also be a struct composed of the type-identifier and the actual value. But that is just an envelope, everything is still explicit.
typedef union {
int i;
float f;
} MyValue;
typedef enum {
MY_VALUE_int,
MY_VALUE_float
} MyValueType;
void func(MyValueType type, MyValue value)
{
switch ( type ) {
...
}
}
int main(void)
{
func(MY_VALUE_int, (MyValueType){ .i=1 });
}
The compound literal argument only works for constants, otherwise you have to assign the value to a union first (or just use that union).
gcc has an extension to avoid this, so you can have a function which takes such a union, but the caller may use a simple cast, instead of a compound literal. That works for variables, too:
func(MY_VALUE_float, (MyValueType)1.0);
An alternative would be passing a const void * and internally casting. However, that is even more risky than the union approach.
All approaches require pasing the actual type explicitly (e.g. using an enum).
C11 allows to create a macro which evaluates different expressions, according to the type of an argument using the new _Generic construct. With that the original approach can be simulated (using gcc extension, normal way is possible, but more complicated):
// use the code of the first block here
#define func_generic(val) _Generic((val), \
int : func(MY_VALUE_int, (MyValueType)(val)), \
int : func(MY_VALUE_int, (MyValueType)(val)) )
// and call like:
func_generic(1);
func_generic(1.0);
However, note the restriction of _Generic: No two compatible types are allowed for the type-selector (i.e. const int and int are not allowed both) for uint16_t and uint32_t this works, however.
Note that gcc (you apparently use) supports C11 using -std=c11 or std=gnu11. The latter also enables GNU-extensions.

The short answer is no.
You have several problems:
1) The different functions all have to have the same signature to allow the function pointer to point to them.
2) The functions are taking their args by value which means a copy will be passed in and any actions you take on the value will not appear to have any affect outside the function call. Since you don't allow pointers I cant see any way round this.
If you are not bothered about problem 2 then you could try declaring a variadic function which will accept args of any type.
e.g.
void doSomethingWithValue(enum MyType type ...)
{
va_list args;
va_start( args, type);
switch( type)
{
case Uint8Type:
{
uint8_t value = va_arg(args, uint8_t);
//doSomething to value
}
break;
.
.
.
}
va_end(args);
}
Where MyType is an enum set up to identify which type is passed in.
which is used like so:
uint8_t value = 7;
doSomethingWithValue(Uint8Type, value);
//note that value is still 7

Note that both of your exampels exibit Undefined Behaviour because you call a function through a pointer of another (function) type.
I found a solution that relies on the fact that there are a limited number of function types known in advance. I think however that it is too much hassle. Just call the original function.
enum GFType {
GF_UINT8,
GF_UINT16 // etc
};
struct GenericFunction {
void (*func)(void);
GFType type;
};
void callGenericFunction(GenericFunction func, uint64_t p) // largest type
{
switch (func.type) {
case GF_UINT8:
((void (*)(uint8_t))func.func)(p);
return;
case GF_UINT16:
((void (*)(uint16_t))func.func)(p);
return;
default:
assert(1); // unimplemented function type
}
}
void setValue(uint8_t byteValue) // Not a pointer parameter
{
byteValue++;
}
void setShortValue(uint16_t byteValue) // Not a pointer parameter
{
byteValue++;
}
int main() {
uint8_t a = 123;
uint16_t b = 321;
GenericFunction pointerFunction;
GenericFunction pointerFunctionShort;
pointerFunction.func = (void (*)(void))setValue;
pointerFunction.type = GF_UINT8;
pointerFunctionShort.func = (void (*)(void))setShortValue;
pointerFunction.type = GF_UINT16;
callGenericFunction(pointerFunction, a);
callGenericFunction(pointerFunctionShort, b);
return 1;
}
Note that
a function-pointer may be freely converted to any other
function-pointer type and back again, and you will get the original
pointer.
This is what we use. We can't even use void * (because it is a data pointer, not a function pointer) to store the function pointer. So I used void (*)(void) to store the function pointer. An enum tells us to what kind of function we must convert it when we need to cal it.

If you can use C11, there is a way to do this using _Generic:
#include <stdio.h>
#include <inttypes.h>
#define setvalue_generic(x) _Generic((x), \
uint8_t: setValue, \
uint16_t: setShortValue \
)(x)
void setValue(uint8_t byteValue)
{
printf("setValue: %" PRIu8 "\n", byteValue);
byteValue++;
}
void setShortValue(uint16_t byteValue)
{
printf("setValue: %" PRIu16 "\n", byteValue);
byteValue++;
}
int main(void)
{
uint8_t a = 123;
uint16_t b = 321;
setvalue_generic(a);
setvalue_generic(b);
return 0;
}
Seems to work well with gcc -std=c11 -pedantic -Wextra -Wall.

#bolov answer is good for handling the different types, this is just a different way of handling the same issue, but with 1 parameter.
The downside to this approach is that the type in main has to be GENERAL_TYPE. In my application I can change the type of the parameter, but I can change the type of the functions that I'm pointing to.
the (void(*)(GENERAL_TYPE))& handles the function's parameter types, and the Union handles the types of all the different sizes.
Another option is to have function pointers for each type too.
typedef union generalType
{
uint8_t byteData;
uint16_t shortData;
uint32_t intData;
int integerData;
uint64_t longData;
void * voidData;
//Add any type
} GENERAL_TYPE;
typedef struct
{
void (*set_func)(GENERAL_TYPE);
} SetFunction;
void setValue(uint8_t byteValue)//Not a pointer parameter
{
byteValue++;
}
void setShortValue(uint16_t byteValue)//Not a pointer parameter
{
byteValue++;
}
int main()
{
GENERAL_TYPE a.byteData = 123;//restricted to use GENERAL_TYPE here
GENERAL_TYPE b.shortData = 321;
SetFunction pointerFuncion;
SetFunction pointerFuncionShort;
//Typecast the setValue parameter to be a general type will
//Allow it to send the data of whatever type.
pointerFunction.set_func = (void(*)(GENERAL_TYPE))&setValue;
pointerFuncionShort.set_func = (void(*)(GENERAL_TYPE))&setShortValue;
//use the function pointer with non-pointer parameter
pointerFunction.set_func(a);
pointerFuncionShort.set_func(b);
}

Related

Which type to use for an arbitrary function pointer in C?

In short, my question is: does the C standard allow for an arbitrary function pointer type similar to void * being an arbitrary data pointer type?
It is common to define call-back function types with a void * parameter to pass on an arbitrary data package whose format is known to the call-back function, but not to the caller.
For example:
typedef void (* EventFunctionType)(void *data);
void RegisterEventFunction(EventFunctionType function, void *data);
An "EventFunction" can then be registered with a data pointer which will be passed to the function when it is called.
Now suppose we want to pass a function pointer to the call-back. The function could have any prototype which would be known to the specific call-back function, just like the arbitrary data structure above.
A void * cannot hold a function pointer, so which type could be used?
Note: An obvious solution to this problem would be to wrap the function pointer in a data structure with the correct function pointer type, but the question is if the function pointer could be passed on directly in a generic form which the call-back could then cast to a pointer with the correct prototype?
There are no function pointer type that works the same as/similar to to void-pointer.
But function pointers has another characteristic that can be used. It's already referenced in the answer linked in this question:
In the C11 draft standard N1570, 6.3.2.3 ยง8:
A pointer to a function of one type may be converted to a pointer to a function of another type and back again.
This mean that you can use any function pointer type as your "arbitrary function pointer type". It doesn't matter as long as you know how to get back to the real/original type (i.e. know the original type so that you can cast correctly).
For instance:
typedef void (*func_ptr_void)(void);
and then use func_ptr_void as your "arbitrary function pointer type".
But notice that unlike conversion between void* and other object pointer types, the conversion between function pointers will always require an explicit cast. The code example below shows this difference:
#include <stdio.h>
typedef void (*func_ptr_void)(void);
typedef int (*f_int)(int);
int bar(int n)
{
return n * n;
}
int test(func_ptr_void f, int y)
{
f_int fc = (f_int)f; // Explicit cast
return fc(y);
}
int foo(void* p)
{
int* pi = p; // Explicit cast not needed
return *pi;
}
int main(void)
{
int x = 42;
void* pv = &x; // Explicit cast not needed
printf("%d \n", foo(pv));
func_ptr_void fpv = (func_ptr_void)bar; // Explicit cast
printf("%d \n", test(fpv, 5));
return 0;
}
does the C standard allow for an arbitrary function pointer type similar to void * being an arbitrary data pointer type?
No. Two function pointers are only compatible if their return types and parameters (including qualifiers) match.
However, pointer conversions between any two function pointers by means of a cast are well-defined (6.3.2.3/8) as long as you don't invoke the function through the wrong pointer type. This means that you can use any function pointer type as a "generic function pointer" as long as you keep track of what function that pointer actually points at. Such as using an extra enum for that purpose.
Generally when using function pointers, we don't do that however, but instead define a common interface. For example like the callbacks to bsearch/qsort which use the form int (*)(const void*, const void*).
Here's an example of "keep track of type using enum", which is not something I particularly recommend but otherwise perfectly well-defined:
#include <stdio.h>
static int intfunc (int x)
{
printf("%d\n", x);
return x;
}
static double doublefunc (double x)
{
printf("%f\n", x);
return x;
}
typedef enum
{
INTFUNC,
DOUBLEFUNC
} functype_t;
typedef void generic_func_t (void);
typedef int int_func_t (int);
typedef int double_func_t (double);
typedef struct
{
generic_func_t* fptr;
functype_t type;
} func_t;
void func_call (const func_t* f)
{
switch(f->type)
{
case INTFUNC: ((int_func_t*)f->fptr ) (1); break;
case DOUBLEFUNC: ((double_func_t*)f->fptr) (1.0); break;
}
}
int main (void)
{
func_t f1 = { (generic_func_t*)intfunc, INTFUNC };
func_t f2 = { (generic_func_t*)doublefunc, DOUBLEFUNC };
func_call(&f1);
func_call(&f2);
}
That's "old school" C, but it is not recommended since it is clunky, brittle and not really type safe. In modern C programming we wouldn't write that kind of code however, but replace that whole mess with something like this:
#include <stdio.h>
static int intfunc (int x)
{
printf("%d\n", x);
return x;
}
static double doublefunc (double x)
{
printf("%f\n", x);
return x;
}
#define func_call(obj) \
_Generic((obj), \
int: intfunc, \
double: doublefunc) (obj) \
int main (void)
{
func_call(1);
func_call(1.0);
}

Declaring void pointers to push type handling downstream

Is it ever common to do something like the following:
void *x = (void *) "one";
void *y = (void *) 2;
void *z = (void *) NULL;
Instead of:
char * x = "one";
int y = 2;
My reason for asking this is the ability to call a function that can accept multiple types. For example, a concat of various elements like is available in javascript. It seems like in a way using (void *) is just a simple way to mean "any type".
No, because you can't dereference a void pointer: you have to know what type is being stored, rendering the idea useless.
What you might be looking for is a variant type.
enum type {
CHAR, INT, DOUBLE, STR
};
typedef struct {
union {
char c;
int i;
double d;
char *str;
};
enum type t;
} variant;
void displayGenericObjec(variant v)
{
switch (v.t) {
case CHAR:
putchar(v.c);
break;
case INT:
printf("%d", v.i);
break;
case DOUBLE:
printf("%f", v.d);
break;
case STR:
printf("%s", v.str);
break;
}
}
variant x;
x.t = INT;
x.i = 42;
displayGenericObject(x);
This isn't a very practical solution, but it works for trivial code that only needs a few types.
Usually, it is not a good idea to write functions that take any argument. As noted in the comments, you lose on the compiler provided type-checking.
However, there are some cases where you might want to consider this using 'void *', which are (usually) considered acceptable are: (1) varargs functions and (2) callback. Important to emphasize that it is better to consider alternative implementation, if possible.
varargs functions are functions like 'printf', 'scanf', etc, where the function can accept variable number of arguments, potentially of different types, and will usually use clues (or convention) from the first arguments to properly decode the remaining arguments.
Callback are other example, where the code will sometimes have to specify a function that will be called on event. Many frameworks will require the callback to match a predefined "typedef", where the code will later cast the arguments into the actual type. For example, the 'qsort' prototype require a 'compar' function, which is generically defined to take 'void *', where the actual function will cast the parameters to the actual type.
void qsort(void *base, size_t nmemb, size_t size,
int (*compar)(const void *, const void *));
On historical note, the initial versions of "C" (sometimes call "K&R C") did allow functions to be defined without formal parameter list. Practical experience has proven this to be risky, non-productive. In those days, you could write function in header files like:
/* in file.h */
int foo() ;
/* in file.c */
int foo(a)
int a ;
{
}
/* in prog.c */
{
a(5,4,"x") ;
}

-Wincompatible-pointer-types and enum

Implicit cast from short* to int* prints the warning about incompatible pointer type (and I understand why).
Implicit cast from enum* to int* prints same warnig.
There's a tool snacc that generates the following code:
typedef enum
{
CHARGINGCALLING = 0,
CHARGINGCALLED = 1,
NONECHARGING = 2
} ChargedParty; /* ENUMERATED { CHARGINGCALLING (0), CHARGINGCALLED (1), NONECHARGING (2) } */
typedef struct MSOriginatingSMSinSMS_IWMSC /* SET */
{
ChargedParty* chargedParty; /* [6] IMPLICIT ChargedParty OPTIONAL */
} MSOriginatingSMSinSMS_IWMSC;
#define BEncChargedPartyContent BEncAsnEnumContent
int BEncMSOriginatingSMSinSMS_IWMSCContent (BUF_TYPE b, MSOriginatingSMSinSMS_IWMSC *v) {
BEncChargedPartyContent (b, (v->chargedParty));
...
}
A header file shipped with this tool:
int BEncAsnIntContent (BUF_TYPE b, int *data);
#define BEncAsnEnumContent BEncAsnIntContent
The call to BEncChargedPartyContent prints the warning.
Can I modify the declaration of BEncAsnEnumContent so it accepts without a warning pointers to any enum, but not void* or short*?
Of course using sed I could replace the macro BEncChargedPartyContent with a static function:
static AsnLen BEncChargedPartyContent (BUF_TYPE b, ChargedParty *data)
{
return BEncAsnEnumContent(b, (int*)data);
}
But there're too many of them.
Your own proposal with a static function sounds not so bad.
Can I modify the declaration of BEncAsnEnumContent so it
accepts without a warning pointers to any enum, but not
void* or short*?
If you want, you can use a static assertion as John Zwinck hinted at.
#define BEncAsnEnumContent(b, d) ({\
_Static_assert(sizeof(int) == sizeof *(d), "wrong data size");\
BEncAsnIntContent(b, (int *)d); })
What you think of in your comment below is a viable alternative with the advantage that it allows enumerations of different sizes; this is how I understand what you mean:
#define BEncAsnEnumContent(b, d) MyEncAsnEnumContent(b, *(d))
static int MyEncAsnEnumContent(BUF_TYPE b, int val)
{
return BEncAsnIntContent(b, &val);
}
The enumeration constants, that is the list of values in your enum declaration, are guaranteed to be of type int. However, this does not apply to the enum variable itself. An enum need not be compatible with int nor with another, different enum type variable. The size can vary from case to case and from compiler to compiler.
This is the root of the problem. If you mix enum and int, or two different enums with each other, all is fine if they have the same size. They are then compatible and you can convert pointers from one of the types to the other without problems.
However, if they are not of the same size, you cannot do this. It would give incompatible types: you would violate the strict aliasing rule and there might also be alignment issues. Plus the obvious: if you try to read a large chunk of data from a location where only a small chunk of data is stored, there's no telling what you will end up with.
The reliable solution is to change your function to simply use an integer type instead of a pointer:
int BEncAsnIntContent (BUF_TYPE b, int data);
There doesn't seem to be a reason why they pass the parameter through a pointer in the first place. Keep it simple.

C: Passing array to pointer function

I'm not sure if the question has asked before, but I couldn't find any similar topics.
I'm struggeling with the following piece of code. The idea is to extend r any time later on without writing lots of if-else statements. The functions (func1, func2...) either take zero or one arguments.
void func1() {
puts("func1");
}
void func2(char *arg){
puts("func2");
printf("with arg %s\n", arg);
}
struct fcall {
char name[16];
void (*pfunc)();
};
int main() {
const struct fcall r[] = {
{"F1", func1},
{"F2", func2}
};
char param[] = "someval";
size_t nfunc = RSIZE(r); /* array size */
for(;nfunc-->0;) {
r[nfunc].pfunc(param);
}
return 0;
}
The code above assumes that all functions take the string argument, which is not the case. The prototype for the pointer function is declared without any datatype to prevent the incompatible pointer type warning.
Passing arguments to functions that do not take any parameters usually results in too few arguments. But in this case the compiler doesn't 'see' this ahead, which also let me to believe that no optimization is done to exclude these unused addresses from being pushed onto the stack. (I haven't looked at the actual assemble code).
It feels wrong someway and that's usually a recipe for buffer overflows or undefined behaviour. Would it be better to call functions without parameters separately? If so, how much damage could this do?
The way to do it is typedef a function with 1 argument, so the compiler could verify if you pass the correct number of arguments and that you do not pass something absolutely incompatible (e.g. a struct by value). And when you initialize your array, use this typedef to cast function types.
void func1(void) { ... }
void func2(char *arg) { ... }
void func3(int arg) { ... }
typedef uintptr_t param_t;
typedef void (*func_t)(param_t);
struct fcall {
char name[16];
func_t pfunc;
};
const struct fcall r[] = {
{"F1", (func_t) func1},
{"F2", (func_t) func2}
{"F3", (func_t) func3}
};
...
r[0].pfunc((param_t) "foo");
r[1].pfunc((param_t) "bar");
r[2].pfunc((param_t) 1000);
Here param_t is defined as uintpr_t. This is an integer type big enough to store a pointer value. For details see here: What is uintptr_t data type.
The caveat is that the calling conventions for param_t should be compatible with the function arguments you use. This is normally true for all integer and pointer types. The following sample is going to work, all the type conversions are compatible with each other in terms of calling conventions:
// No problem here.
void ptr_func(struct my_struct *ptr) {
...
}
...
struct my_struct struct_x;
((func_t) &ptr_func)((param_t) &struct_x);
But if you are going to pass a float or double argument, then it might not work as expected.
// There might be a problem here. Depending on the calling
// conventions the value might contain a complete garbage,
// as it might be taken from a floating point register that
// was not set on the call site.
void float_func(float value) {
...
}
...
float x = 1.0;
((func_t) &float_func)((param_t) x);
In this case you might need to define a function like this:
// Problem fixed, but only partially. Instead of garbage
// there might be rounding error after the conversions.
void float_func(param_t param) {
float value = (float) param;
...
}
...
float x = 1.234;
((func_t) &float_func)((param_t) x);
The float is first being converted to an integer type and then back. As a result the value might be rounded. An obvious solution would be to take an address of x and pass it to modified a function float_func2(float *value_ptr). The function would dereference its pointer argument and get the actual float value.
But, of course, being hardcore C-programmers we do not want to be obvious, so we are going to resort to some ugly trickery.
// Problem fixed the true C-programmer way.
void float_func(param_t param) {
float value = *((float *) &param);
...
}
...
float x = 1.234;
((func_t) &float_func)(*((param_t *) &x));
The difference of this sample compared to passing a pointer to float, is that on the architecture (like x86-64) where parameters are passed on registers rather than on the stack, a smart enough compiler can make float_func do its job using registers only, without the need to load the parameter from the memory.
One option is for all the functions accept a char * argument, and your calling code to always pass one. The functions that don't need an argument need not use the argument they receive.
To be clean (and avoid undefined behaviour), if you must have some functions that accept no argument and some functions that accept an argument, use two lists and register/call each type of function separately.
If the behaviour is undefined there's no telling how much damage could be caused.
It might blow up the planet. Or it might not.
So just don't do it, OK?

Cast to function pointer

I have come across the line of code shown below.
I think it may be a cast to a function pointer that returns void and takes a void pointer. Is that correct?
(void (*)(void *))SGENT_1_calc
Yes, it is correct. I find that not very readable, so I suggest declaring the signature of the function to be pointed:
typedef void sigrout_t(void*);
I also have the coding convention that types ending with rout_t are such types for functions signatures. You might name it otherwise, since _t is a suffix reserved by POSIX.
Later on I am casting, perhaps to call it like
((sigrout_t*) SGENT_1_calc) (someptr);
Yes, it is. The function should be looking like this
void func(void*);
But the statement is missing a target, since a cast to nothing is useless. So it should be like
func = (void (*)(void *))SGENT_1_calc;
None of the existing answers show it in direct usage, that is, taking a function pointer and casting it in order to call the function. I was playing with this to show the content of my object as json, accessing both the function and the data through anonymous pointers:
#include <stdio.h>
#include <stdlib.h>
typedef struct box1_s{
int a;
char b[50];
}box1_t;
void box1_t_print(void* ptr){
box1_t* box = (box1_t*)ptr;
printf("{\"a\": %i, \"b\": \"%s\"}", box->a, box->b);
}
int main(){
void* print = (void*)box1_t_print;
box1_t mybox = {3, "Hi folks, it's me!"};
void* ptr = &mybox;
printf("mybox = ");
((void (*)(void*))print)(ptr);
return 0;
}
Output of the program:
mybox = {"a": 3, "b": "Hi folks, it's me!"}
Yes, this is a function pointer cast.
Function pointer casts
To help you with casting functions to pointers, you can define an alias for a function pointer type as follows:
typedef void void_to_void_fct(void*);
You can also define a type for a function that takes and returns values:
typedef int math_operator(int, int);
Later, you can store a function into a function pointer type like this:
void mystery(void* arg) {
// do something nasty with the given argument
};
int add(int a, int b) {
return a + b;
}
void_to_void *ptr1 = mystery;
math_operator *ptr2 = add;
Sometimes, you have a function like print_str :
void print_str(char* str) {
printf("%s", str);
}
and you want to store it in your function pointer that is agnostic to the argument type. You can then use a cast like this:
(void (*)(void *))print_str
or
(void_to_void_fct*)print_str
Why do we use function pointers?
Function pointers allow you to "store a function" inside a variable (indeed, you store the address of the function). This is very convenient when you want to allow some code to have diferent behavior depending on user input.
For exemple, suppose we have some data and some way to decode it. We could have the following structure to keep this information:
typedef char* decoder_type(char*);
struct encoded_data {
char* data;
decoder_type *decoder_fct;
};
char* decoding_function_1(char* data) {
//...
char* decoding_function_2(char* data) {
//...
This allows storing both the data and the function to later use them together to decode the data.

Resources