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

Aym*_*nTM 0 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.
Run Code Online (Sandbox Code Playgroud)

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

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

但我的猜测是错误的:

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


那么如何访问其中一个函数呢?

Lun*_*din 8

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

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

稍微好一点的是使用函数指针类型,例如void (*)(void)泛型指针.您可以转换为/从不同的函数指针转换,将发生的是特定于编译器(实现定义的行为).也就是说,代码仍然是不可移植的,但至少你不会冒程序崩溃来调用未定义的行为.


Som*_*ude 5

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

这意味着你的表达(int (*)(int)) functions[0](x)非常相等(int (*)(int)) (functions[0](x)).

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


一个更好的解决方案IMO将有一个指向函数的数组,因此数组元素的类型正确:

typedef int (*function_ptr)(int);

function_ptr functions[] = { ... };
Run Code Online (Sandbox Code Playgroud)

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

那么你也可以安全地解决Lundin答案中提到的问题.