C:如何访问存储在 void 指针 (void *) 中的函数指针?



对如何访问存储在 void 指针 (void *( 中的函数指针感到困惑。


假设你有这个:

void *functions[] =
{
&sqrt,         // int ft_sqrt(int nb);
&power,
&logN,
&factorial;
};
// An array of void pointers, each storing a function pointer.

如果我想访问sqrt功能,我的猜测如下:

(int (*)(int)) functions[0](x)

但我的猜测是错误的:

error: called object type 'void *' is not a function or function pointer


那么如何访问这些功能之一呢?

严格来说,你不能。函数指针和void指针之间的转换是不可能的。void*从来都不是函数指针的通用指针类型,而只是对象指针的通用指针类型。它们不是兼容的类型。

实际上,任何指针都很可能具有系统地址总线所需的大小,因此对象指针和函数指针很可能具有相同的表示形式。但是,标准不能保证,并且有一些奇特的系统,这种等价性并不成立。因此,您可以在void*和函数指针之间进行强制转换,但将发生的是未定义的行为。您将依赖特定于系统的非标准扩展。

稍微好一点的是使用函数指针类型(如void (*)(void)(作为泛型指针。您可以与不同的函数指针相互转换,将发生的事情是特定于编译器的(实现定义的行为(。也就是说,代码仍然是不可移植的,但至少您不会因调用未定义的行为而冒程序崩溃的风险。

这是运算符优先级的问题:函数调用运算符的优先级高于强制转换运算符。

这意味着您的表达式(int (*)(int)) functions[0](x)实际上等于(int (*)(int)) (functions[0](x))

您需要在正确的位置显式添加括号以强制转换指针:((int (*)(int)) functions[0])(x)


IMO 更好的解决方案是拥有一个指向函数的指针数组,因此数组元素已经属于正确的类型:

typedef int (*function_ptr)(int);
function_ptr functions[] = { ... };

然后不需要铸造:functions[0](x).

那么你也可以免受伦丁回答中提到的问题的影响。