C:如何访问存储在空指针(void *)中的函数指针?
C: How to access a function pointer stored in a void pointer (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
那么如何访问这些功能之一呢?
这是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)
.
那么您也不会遇到 中提到的问题。
严格来说,你不能。函数指针和 void
指针之间的转换是不可能的。 void*
从来都不是函数指针的通用指针类型,仅适用于对象指针。它们不是兼容的类型。
实际上,任何指针都可能具有系统地址总线所需的大小,因此对象指针和函数指针很可能具有相同的表示形式。虽然标准没有保证,但在一些奇异的系统中,这种等价性并不成立。所以你可以在 void*
和一个函数指针之间转换,但是会发生未定义的行为。您将依赖系统特定的非标准扩展。
稍微好一点的方法是使用函数指针类型,例如 void (*)(void)
作为通用指针。您可以转换 to/from 不同的函数指针,将会发生什么是特定于编译器的(实现定义的行为)。也就是说,代码仍然是不可移植的,但至少您不会因调用未定义的行为而冒程序崩溃的风险。
对于如何访问存储在 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
那么如何访问这些功能之一呢?
这是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)
.
那么您也不会遇到
严格来说,你不能。函数指针和 void
指针之间的转换是不可能的。 void*
从来都不是函数指针的通用指针类型,仅适用于对象指针。它们不是兼容的类型。
实际上,任何指针都可能具有系统地址总线所需的大小,因此对象指针和函数指针很可能具有相同的表示形式。虽然标准没有保证,但在一些奇异的系统中,这种等价性并不成立。所以你可以在 void*
和一个函数指针之间转换,但是会发生未定义的行为。您将依赖系统特定的非标准扩展。
稍微好一点的方法是使用函数指针类型,例如 void (*)(void)
作为通用指针。您可以转换 to/from 不同的函数指针,将会发生什么是特定于编译器的(实现定义的行为)。也就是说,代码仍然是不可移植的,但至少您不会因调用未定义的行为而冒程序崩溃的风险。