How do I declare a function pointer that can safely point to any function?
I need something like void pointers, but for functions. I thought about simply using that but, according to the answers to this question, function pointers cannot be reliably converted to data pointers, at least on non-POSIX systems.
I searched and found some possible examples of this:
-
Windows has FARPROC:
int (FAR WINAPI * FARPROC) ()The documentation also mentions this:
In C, the FARPROC declaration indicates a callback function
that has an unspecified parameter list.Sounds fine, but what about the return value? It is clearly specified as
int. -
One of OpenGL’s specifications has:
typedef void (*GLfunction)(); extern GLfunction glXGetProcAddressARB(const GLubyte *procName);The parameter list is also unspecified, but the return type is clearly specified as
void.
I’m not sure how to interpret this. The function pointer will be cast to a function pointer type with the appropriate prototype before it is used. For example:
typedef void (*function_pointer_t)();
extern function_pointer_t get_function(const char * name);
/* Somewhere else... */
typedef double (*cosine_function_t)(double);
cosine_function_t cosine = (cosine_function_t) get_function("cos");
Is this code safe? Does it violate any C standard or result in any undefined behavior?
Firstly, there’s no way to declare a function pointer that would be able to accept any function pointer type without a cast. The problem, as you already noted yourself, is that any function pointer declaration immediately assumes a specific return type. So, there’s no such thing as full analogue of
void *in function pointer world.Secondly, any function pointer can be used to store any other function pointer value as long as you force the conversion by using an explicit cast. Of course, in order to perform a proper call through a pointer forcefully converted to a different type you need to convert it back to the original type. I.e. this does not cause any undefined behavior as long as the proper function pointer type is restored at the moment of the call.
In your example if the pointer returned by
get_functionreally points to a function ofdouble (double)type, then it is perfectly safe to call that function throughcosinepointer. The fact that the pointer value was stored intermediately in avoid (*)()pointer does not destroy it.Thirdly, in C language a
()parameter declaration stands for unspecified number and types of parameters. This is a step in the direction of the "universal" function pointer type that can be used without a cast (as long as you supply proper parameters in the call and as long as the return type matches)But, again, the problem of return type still remains.