Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Pointers to any function?

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?

like image 857
Matheus Moreira Avatar asked Oct 06 '12 19:10

Matheus Moreira


People also ask

Why do we use pointers to functions?

Function pointers can be useful when you want to create callback mechanism, and need to pass address of a function to another function. They can also be useful when you want to store an array of functions, to call dynamically for example.

What is pointer to function in C++ with example?

Passing Pointers to Functions in C++C++ allows you to pass a pointer to a function. To do so, simply declare the function parameter as a pointer type. Following a simple example where we pass an unsigned long pointer to a function and change the value inside the function which reflects back in the calling function −

How do you call a function from a pointer?

The call by pointer method of passing arguments to a function copies the address of an argument into the formal parameter. Inside the function, the address is used to access the actual argument used in the call. This means that changes made to the parameter affect the passed argument.


2 Answers

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_function really points to a function of double (double) type, then it is perfectly safe to call that function through cosine pointer. The fact that the pointer value was stored intermediately in a void (*)() 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)

void foo(void);
void bar(int i);
void baz(long i, double x);

int main() {
  void (*a[3])() = { foo, bar, baz };
  a[0]();
  a[1](42);
  a[2](5L, 3.1415);
}

But, again, the problem of return type still remains.

like image 83
AnT Avatar answered Oct 12 '22 23:10

AnT


You can use a union. There are surely only a finite number of function types that you call via this pointer, and you can put them all in the union.

like image 40
Jim Balter Avatar answered Oct 13 '22 00:10

Jim Balter