【问题标题】:Function that returns a pointer to function using parameter passed使用传递的参数返回指向函数的指针的函数
【发布时间】:2021-02-13 18:12:39
【问题描述】:

我对如何实现以下内容有点困惑。我想要一个函数,func2,返回一个函数,调用 func1 并指定参数:

int func1(int x, int y, int z, int type){
    
    // Calculations
}

int ((*func2)(int x, int y, int z))(int type){

    // Return a pointer to func1 that with get x, y, z as parameters 
    // when called later, with type = type being fixed
}

用途:

my_func = func2(3);
printf("result = %d\n", my_func(1,2,3));

【问题讨论】:

  • 这能回答你的问题吗? Is there a a way to achieve closures in C
  • 这个问题有很多现有的答案。请参阅重复链接。有些使用FFCALL,有些只是直接C。
  • 嗯,看起来 GNU 也有一个 callback library。这些解决方案的优点是它们为您提供了一个具有自己关联状态的可调用函数。不幸的是,没有办法直接在 C 中实现。

标签: c function pointers parameters


【解决方案1】:

这就是我认为你想要的:

int func1( int x, int y, int z )
{
  ...
}

/**
 * func2 takes an integer parameter and returns a
 * pointer to a function that takes 3 integer
 * parameters and returns int
 */
int (*func2(int type))(int, int, int)
{
  /**
   * This example is based on what you wrote in your 
   * question.  Regardless of how you actually select
   * which function to return based on the input, the
   * return statement will be the same.
   */
  switch ( type )
  {
    case 3:
      return func1;
      break;

    default:
      break;
  }
  return NULL;
}

int main( void )
{
  int (*my_func)(int, int, int);
  ...
  my_func = func2( 3 );
  if ( my_func )
    printf( "result = %d\n", my_func( 1, 2, 3 ) );
  ...
}

如果你写 func2 以至于它永远不会返回 NULL 并且你希望你的同事向你扔东西,你可以省略 my_func 变量而只写

printf( "result = %d\n", func2(3)(1, 2, 3));

我不推荐它,除非你喜欢代码审查中粗鲁的 cmets。

【讨论】:

    【解决方案2】:

    函数指针语法有点混乱,但你可以更容易地对函数本身进行类型定义。然后你可以使用“正常”的指针语法。

    typedef int func(int,int,int);
    
    int func1(int x, int y, int z){
        // Calculations
        return 1;
    }
    
    int func2(int x, int y, int z){
        // Calculations
        return 2;
    }
    
    int func3(int x, int y, int z){
        // Calculations
        return 3;
    }
    
    
    func *selectfunc(int type)
    {
        func *f = NULL;
        switch(type)
        {
            case 1:
                f = func1;
                break;
            case 2:
                f = func2;
                break;
            case 3:
                f = func3;
                break;
        }
        return f;
    }
    
    
    int main(void)
    {
        int type = rand()%3;
        printf("%d", selectfunc(type)(1,2,3));
    }
    

        func *fptr = selectfunc(2);
        fptr(1,2,3);
    

    【讨论】:

    • 感谢您尝试为我提供接近我所想的格式的解决方案!不过,type 可以获取范围广泛的值,不能用作函数选择器。
    • 这只是一个例子
    • 它不会将type 传递给func1。我希望type 获取一次值,然后在调用fptr(1,2,3) 时使用该值执行计算。
    • 所以修改你的问题。你认为我是从你的脑海中通过心灵感应读取的吗?在您的示例中,函数指针还传递 3 参数
    • 我认为在func1的声明中很清楚,它需要4个参数。
    【解决方案3】:

    为此,您需要一个称为 closure 的东西,它基本上是一个记录,其中函数和类型作为字段。下面是一个例子来说明这个想法。在实际程序中,您还需要检查 malloc 是否返回 NULL,并释放内存。

    #include <stdio.h>
    #include <stdlib.h>
    
    typedef struct ClosureDesc *Closure;
    
    struct ClosureDesc {
        int type;
        int (*function)(Closure c, int x, int y, int z);
    };
    
    
    int func1(Closure c, int x, int y, int z)
    {
        return c->type;
    }
    
    
    Closure func2(int type)
    {
        Closure c;
    
        c = malloc(sizeof *c);
        c->type = type;
        c->function = func1;
        return c;
    }
    
    
    int main(void)
    {
        Closure my_func;
    
        my_func = func2(3);
        printf("result = %d\n", my_func->function(my_func, 1,2,3));
        return 0;
    }
    

    【讨论】:

    • 您在完成后省略了释放闭包这一最重要的步骤。最好不要将指针埋在typedef 中,而是将其公开以便人们意识到它(这可能会防止内存泄漏错误)。
    • @TomKarzes 确实,但在这个简短的示例中,它将在程序退出时被释放。更新了答案以突出显示这一点。
    • 这是一个不好的看法。 OP 需要知道如何在“等到退出以释放所有内容”上下文中使用它。它有将指针隐藏在typedef 中的不良做法,这使得它更有可能出现这样的错误。
    • 但它不会根据类型选择正确的功能。那么解决方案在哪里?
    • @P__JsupportswomeninPoland 这完全取决于你如何解释这个问题。
    猜你喜欢
    • 2013-04-10
    • 2011-01-12
    • 2015-08-05
    • 1970-01-01
    • 2020-04-29
    • 2019-08-17
    • 2020-09-06
    • 1970-01-01
    • 2012-05-03
    相关资源
    最近更新 更多