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

时间:2018-08-29 06:31:13

标签: c pointers function-pointers void-pointers typecasting-operator

对于如何访问存储在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


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

2 个答案:

答案 0 :(得分:8)

严格来讲,不能。无法在函数指针和void指针之间进行转换。 void*从来不是函数指针的通用指针类型,仅是对象指针。它们是不兼容的类型。

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

稍微好一点的方法是使用诸如void (*)(void)之类的函数指针类型作为通用指针。您可以在不同的函数指针之间进行转换,这将是编译器特定的(实现定义的行为)。也就是说,代码仍将是不可移植的,但是至少您不会因调用未定义的行为而冒着程序崩溃的风险。

答案 1 :(得分:5)

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

这意味着您的表达式(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)

然后,您也将免受the answer by Lundin中提到的问题的困扰。