Define and use the function pointer type, referring to functions with parameters of different enumeration types
I have a couple of functions that take multiple parameters. Both function signatures are of the same type, except for one parameter enum:
typedef enum { a_1, a_2, a_3 } enum_a_t;
typedef enum_a_t * enum_a_p;
typedef enum { b_1, b_2 } enum_b_t;
typedef enum_b_t * enum_b_p;
void func_a(int ai, float af, enum_a_p ae_ptr) { /* blah */ }
void func_b(int ai, float af, enum_b_p ae_ptr) { /* blah */ }
Now, since in my head I think that enums are done as integers, I thought that maybe I could typedef a function that is compatible with both of these signatures, something like:
typedef void (* func_t)(int, float, int *);
But of course, when assigning any of these functions to a variable of this type (for example func_t f_a = func_a
), llvm-gcc complains:
warning: incompatible pointer types initializing 'func_t' (aka 'void (*)(int, float, int *)') with an expression of type 'void (int, float, enum_a_p)' (aka 'void (int, float, enum_a_t *)') [-Wincompatible-pointer-types]
I understand this is just a warning, and I can probably get away with it if I'm careful, but I was curious if there is a strict / type safe to do something like this in C?
I wish I had no warning about the assignment, and I would like to be able to treat these functions as a generic type without changing their declared parameter lists.
change
This is a very small example of a problem I encountered in a much larger codebase. Changing the declared parameter lists would require typecasting all direct calls to those functions elsewhere in the code - a significant change that would require a lot of testing of the integration (testing days and then involving others (this on a weird embedded platform)) in areas of code that I really don't needs to be changed.
source to share
Assuming the two functions could be changed, I would change the two functions to format:
void func_a(int ai, float af, void * ae_ptr) { /* blah */ }
void func_b(int ai, float af, void * ae_ptr) { /* blah */ }
Then, when you enter each of the two functions, go to the appropriate type enum_a_p or enum_b_p when referencing the data.
source to share
To call a function using a function pointer with the described arguments, the arguments must be compatible. Pointers to different types are not compatible. One solution is to declare functions without a prototype, and then declare a function pointer with no arguments (more precisely, with undefined number of arguments):
void func_a();
void func_b();
void func_a(int ai, double af, enum_a_p ae_ptr) { /* blah */ }
void func_b(int ai, double af, enum_b_p ae_ptr) { /* blah */ }
typedef void (* func_t)();
Alternatively, you can use ellipsis:
void func_a(int ai, double af, ...) { /* blah with varargs */ }
void func_b(int ai, double af, ...) { /* blah with varargs */ }
typedef void (* func_t)(int ai, double af, ...);
Note, however, that in both cases the default type rules apply - so the af argument must be changed from float to double type.
source to share