C: What even is function pointer conversion? [clos

2019-05-31 22:57发布

问题:

Let's say one wanted to create an array that could hold multiple function pointers & of different types.. how would he go about doing so ? Perhaps an array of void pointers could work ?... Well as it turns out, no since in order to use the functions stored in the void pointers you'd have to convert/cast them (the void pointers) back to function pointers and...

"A conversion between a function pointer and a void pointer is not possible. void* was never a generic pointer type for function pointers, only for object pointers. They are not compatible types.

[...] you can cast between void* and a function pointer, but what will happen is undefined behavior. You will be relying on system-specific non-standard extensions."

-@Lundin (here)

Instead...

Slightly better would be to use a function pointer type such as void (*)(void) as the generic pointer. You can convert to/from different function pointers, what will happen is compiler-specific (implementation-defined behavior). That is, the code will still be non-portable, but at least you don't risk a program crash from invoking undefined behavior.

-@Lundin (here)


That said, what does it even mean to convert from one function pointer to another ?

Could someone explain it. With an example perhaps.

回答1:

It means that if you have two different function pointer types, such as for example:

int (*i)(int);
void (*v)(void);

Then you can make a conversion from one type to the other by using an explicit cast:

v = (void(*)(void))i;

This is allowed, but calling v() won't work. The standard says this, C17 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; the result shall compare equal to the original pointer. If a converted pointer is used to call a function whose type is not compatible with the referenced type, the behavior is undefined.

So if you try to call the function by v(); then it is likely undefined behavior. You can however convert back to the original type int(*)(int) without losing information.

This allows you to use a specific function pointer type as a "generic type". Rather than using void*, which isn't ok, as discussed here.


Notably, all code with function pointers get much easier to read if you use typedefs:

typedef int int_func (int);
typedef void void_func (void);

int main() 
{
  int_func*  i;
  void_func* v;

  v = (void_func*) i;

  i = (int_func*) v;
}