Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/65.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C 如何通过调用堆栈传递函数指针?_C - Fatal编程技术网

C 如何通过调用堆栈传递函数指针?

C 如何通过调用堆栈传递函数指针?,c,C,我不确定我是否有这个问题的最佳标题,请随意改进 如果我有 typedef void (*VoidFunction)(void); 然后是一系列适合这种类型的函数,我可以编写一种“事务”包装函数,类似于: void doTransaction(VoidFunction function) { doSomePreambleWork(); function(); doSomePostambleWork(); } // ????? I'm not sure how i'd t

我不确定我是否有这个问题的最佳标题,请随意改进

如果我有

typedef void (*VoidFunction)(void);
然后是一系列适合这种类型的函数,我可以编写一种“事务”包装函数,类似于:

void doTransaction(VoidFunction function)
{
    doSomePreambleWork();
    function();
    doSomePostambleWork();
}
// ????? I'm not sure how i'd type the passed function
void doTransactionGeneric(void * function, ...)
{
    doSomePreambleWork();
    function(); // ????? and i don't know how i'd go about calling it...
    doSomePostambleWork();
}
如果我有一系列函数采用单个int参数,我可以重复:

typedef void (*VoidOneIntFunction)(int a);
void doTransactionOneInt(VoidFunctionOneInt function, int a)
{
    doSomePreambleWork();
    function(a);
    doSomePostambleWork();
}
离开返回类型的问题(iow,假设返回类型为void),是否可以将此模式泛化,这样我只需编写一个包装函数,比如:

void doTransaction(VoidFunction function)
{
    doSomePreambleWork();
    function();
    doSomePostambleWork();
}
// ????? I'm not sure how i'd type the passed function
void doTransactionGeneric(void * function, ...)
{
    doSomePreambleWork();
    function(); // ????? and i don't know how i'd go about calling it...
    doSomePostambleWork();
}
我不确定如何键入传递的函数

就像在其他任何地方声明函数指针一样:

void doTransactionGeneric(void (*function)(void), ...)
我不知道该怎么称呼它

就像你已经做的那样:

function();

如果您想使用
..
语法,即可变参数,则可以使用
va_list
访问参数列表,例如:

#include <stdarg.h>

typedef void (*VoidArgsFunction)(va_list args);

void doTransactionGeneric(VoidArgsFunction function, ...)
{
    doSomePreambleWork();

    va_list args;
    va_start(args, function);
    function(args);
    va_end(args);

    doSomePostambleWork();
}
这里有一个建议

假设您有多个功能(如您的问题中所述):

让我们定义类型枚举(我们不必使用枚举,但这更能说明问题):

然后,假设我们有一些通用处理器。我们需要提供函数类型、函数指针和参数:

void some_generic_function(void_function_kind_t kind, void *fn, ...)
{
   va_list args;
   va_start(args, fn);

   // here - make a call
   switch (kind)
   {
   case e_fn_void:
        // no arguments
        ((VoidFunction)fn)();
        break;
   case e_fn_void_int:
        {
           int arg0 = va_arg(args,int);
           ((VoidFunctionOneInt)fn)(arg0);
        }
        break;
   default: // error - unsupported function type
        break;
   }

   va_end(args);
}

查看
标题。解决方法是使用可变参数列表。@Will我不认为这是OP所要求的。我希望得到比这些答案更“元”的东西。也许用C是不可能的。我想我可能会以某种方式弄乱堆栈,用调用堆栈的其余部分神奇地调用调用堆栈的第一个参数(已知为函数)(如果这样声明
函数
,则无法将可变参数传递给
doTransactionGeneric()
本身并将其传递给指定的函数。
void some_generic_function(void_function_kind_t kind, void *fn, ...)
{
   va_list args;
   va_start(args, fn);

   // here - make a call
   switch (kind)
   {
   case e_fn_void:
        // no arguments
        ((VoidFunction)fn)();
        break;
   case e_fn_void_int:
        {
           int arg0 = va_arg(args,int);
           ((VoidFunctionOneInt)fn)(arg0);
        }
        break;
   default: // error - unsupported function type
        break;
   }

   va_end(args);
}