提问人:ADBeveridge 提问时间:5/17/2022 更新时间:5/19/2022 访问量:443
使用指针调用函数,并在参数中传递可以指向函数的指针
Call a function using a pointer and pass the pointer that can point to the function along in the parameters
问:
假设我有一个指向函数的指针。 带一个指针,该指针可以指向与 具有相同参数列表的任何函数,因此调用的函数可以将传递的指针设置为 NULL 或其他函数。theFunc
theFunc
theFunc
使用它将如下所示:
while (funcPtr != NULL)
{
funcPtr(&funcPtr);
}
定义这是不可能的吗?
答:
是的,您可以将指针传递到函数的指针。如果使用 typedefs,语法会容易得多。
typedef void somefunc(void);
void func1(void)
{
printf("Func1\r");
}
void func2(void)
{
printf("Func2\r");
}
void swapfunction(somefunc **ptr)
{
if(*ptr == func1) *ptr = func2;
else *ptr = func1;
}
int main(void)
{
somefunc *ptr = NULL;
swapfunction(&ptr);
ptr();
swapfunction(&ptr);
ptr();
}
您还可以使用函数返回值:
typedef void somefunc(void);
void func1(void)
{
printf("Func1\r");
}
void func2(void)
{
printf("Func2\r");
}
somefunc *swapfunction(somefunc *ptr)
{
if(!ptr) return func1;
else if (ptr == func1) return func2;
else return NULL;
}
int main(void)
{
somefunc *ptr = NULL;
while(ptr = swapfunction(ptr))
{
ptr();
}
}
评论
ptr()
ptr(&ptr);
这种工作方式:
#include <stdio.h>
void *a(void)
{
printf("Calling a()\n");
return NULL;
}
void *b(void)
{
printf("Calling b()\n");
return a;
}
void *c(void)
{
printf("Calling c()\n");
return b;
}
int main(void)
{
void *(*funcPtr)(void) = &c;
while (funcPtr) {
funcPtr = funcPtr();
}
}
我真的没有看到好的用途,尤其是在将指向函数本身的指针作为参数传递时(我为什么省略它),但无论什么让你的船漂浮。当然,您可以将参数替换为您需要的任何参数。
你可以添加一个 typedef 来对类型有所帮助:
typedef void *(*myfunc)(void);
然后,您可以执行以下操作:
myfunc funcPtr = &c;
// instead of: void *(*funcPtr)(void) = &c;
我不认为这些特别优雅,但它应该有效。
请注意,是否将 或 分配给 myfunc,或者是否返回或从其中一个函数返回都无关紧要。c
&c
a
&a
评论
void *
是的,这是可行的。
简单的方法:
void (*fptr_t)(void*);
函数指针是数据,即使它指向非数据。因此,可以将指向函数指针的指针转换为,而无需依赖编译器扩展。void*
该解决方案缺乏类型安全性。但是,它可以改进。
目前,可以声明一个采用未指定数量的参数的函数。它允许形成一个不完整的函数类型。例如:
int foo();
声明一个函数,该函数返回并采用未指定的参数。要使函数不带参数,请使用 。int
int foo(void)
这允许声明一个函数,该函数采用指向指向不完整函数类型的指针的指针:
int foo(int (**)());
// call
int (*fptr)(int (**)()) = foo;
fptr(&fptr);
正如其他答案中提到的,-ing 函数类型使代码更简洁。typedef
typedef int foo_aux_f();
typedef int foo_f(foo_aux_f**);
foo_f *fptr = &foo;
fptr(&fptr);
通过越来越深地嵌套函数类型的声明,可以提高类型安全性。
typedef int foo_aux0_f();
typedef int foo_aux1_f(foo_aux0_f**);
typedef int foo_aux2_f(foo_aux1_f**);
typedef int foo_aux3_f(foo_aux2_f**);
typedef int foo_f(foo_aux3_f**);
foo_f fptr = &foo;
fptr(&fptr);
完美的递归类型可以通过无限的声明链来达到,但在实践中,2-3 个级别就足够了。
通过对关键字语法的一些滥用,可以压缩这种类型的声明:typedef
typedef int foo_aux0_f(),
foo_aux1_f(foo_aux0_f**),
foo_aux2_f(foo_aux1_f**),
foo_aux3_f(foo_aux2_f**),
foo_f(foo_aux3_f**);
不幸。。。或者幸运的是,这个技巧在即将到来的 C23 中可能不起作用,因为计划从语言中删除没有原型的旧函数声明,这意味着没有参数,而不是未指定数量的参数。()
评论
引用你的 github 评论,建议你使用结构而不是类型将指针转换为函数指针等。这并不完全是您所要求的,而是有点。 然后,代码将如下所示:
#include <stdio.h>
struct funcArgStruct
{
void (*state)(struct funcArgStruct *);
// int extra_data; // optional
};
typedef struct funcArgStruct funcArg;
void start (funcArg *ptr);
void task1 (funcArg *ptr);
void stop (funcArg *ptr);
/* Implementation of an fsm. */
int main()
{
funcArg ptr_, *ptr = &ptr_;
ptr->state = start;
// ptr->extra_data = 0; // optional
while (ptr->state != NULL)
{
ptr->state(ptr);
}
return 0;
}
void start (funcArg *ptr)
{
ptr->state = task1;
}
void stop (funcArg *ptr)
{
ptr->state = NULL;
}
void task1 (funcArg *ptr)
{
ptr->state = stop;
}
评论
void *
typedef void (*myGenericFuncPtr)(void);