【问题标题】:Returning function pointer type返回函数指针类型
【发布时间】:2014-01-04 04:57:30
【问题描述】:

我经常发现需要编写返回函数指针的函数。每当我这样做时,我使用的基本格式是:

typedef int (*function_type)(int,int);

function_type getFunc()
{
   function_type test;
   test /* = ...*/;
   return test;
}

但是在处理大量函数时这会变得很麻烦,所以我不想为每个函数(或每个函数类)声明一个 typedef

我可以删除 typedef 并将函数中返回的局部变量声明为: int (*test)(int a, int b); 让函数体看起来像这样:

{
     int (*test)(int a, int b);
     test /* = ...*/;
     return test;
}

但是我不知道为函数的返回类型设置什么。 我试过了:

int(*)(int,int) getFunc()
{
    int (*test)(int a, int b);
    test /* = ...*/;
    return test;
}

但是会报告语法错误。如何在不为函数指针声明 typedef 的情况下声明此类函数的返回类型。甚至可能吗?另请注意,我知道为每个函数声明 typedef 似乎会更干净,但是,我非常小心地将我的代码构造为尽可能干净和易于遵循。我想消除 typedef 的原因是它们通常只用于声明检索函数,因此在代码中看起来是多余的。

【问题讨论】:

  • +1,很有趣,我之前也在想自己,只是使用了 typedef 。
  • 不应该test_typefunction_type 吗? (并不是说它有那么重要,只是为了完全清楚。)
  • 您在问题中遗漏了一些内容(例如,test_type 的定义是什么)。当我们感到困惑时,使回答您的问题变得更加困难。大声笑
  • @SE 是的。我试图想出一个很好的例子来作为答案发布,除非你认为这不是要走的路......
  • @AndyLin 有很多。几乎任何时候您都必须编写库包装器。只是从我的脑海中挑选一个真实世界的例子,假设您正在编写一个 opengl 应用程序并希望支持动态加载用户系统上的任何版本的 opengl。然后,您围绕 open gl 编写一个包装器,并从库中动态加载您使用的每个 gl 函数。在这种情况下,在初始化时,您希望通过在该版本的 open gl 中查找其名称来返回每个 gl 函数。事实上,open gl 有一些旨在以这种方式加载的扩展

标签: c syntax types function-pointers


【解决方案1】:

您可能可以这样做:

int foo (char i) {return i*2;}

int (*return_foo()) (char c)
{
   return foo;
}

但是上帝,我希望我永远不必调试你的代码......

【讨论】:

  • 正如我在问题中所说,我不会在它使代码混乱的情况下使用它。仅适用于声明大量 typedef 是多余的极少数情况
  • 哎呀!再读一遍,有点粗鲁,对不起,我不是那个意思 - 这是一个笑话。
【解决方案2】:

可以编写如下代码(仅适用于C++11及以上):

//C++11
auto func(...) {
    int (*fptr)(...) ret = ...
    //Do sth.
    return ret;//C++11 compiler will automatically deduce the return type for you
}

或者,如果你不喜欢自动推导返回类型,可以在函数末尾指定类型(同上,仅在C++11及以上):

//C++11
auto func(...) -> int (*)(...) { /* Do sth. */ }

【讨论】:

  • 感谢您的回答,但问题是关于 c 而不是 c++。
【解决方案3】:

我把它留在这里,因为它比已经给出的答案有点棘手,因为它需要一个函数指针

(int (__cdecl *)(const char *))

并返回一个函数指针

(int (__cdecl *)(const char *))

#include <stdio.h>

int (*idputs(int (*puts)(const char *)))(const char *) {
    return puts;
}

int main(int argc, char **argv)
{
    idputs(puts)("Hey!");

    return 0;
}

【讨论】:

    【解决方案4】:
    int (*getFunc())(int, int) { … }
    

    这提供了您要求的声明。此外,正如ola1olsson 所说,最好插入void

    int (*getFunc(void))(int, int) { … }
    

    这表示getFunc 可能不带任何参数,这有助于避免错误,例如有人无意中写了getFunc(x, y) 而不是getFunc()(x, y)

    【讨论】:

    • 我有一个类成员函数,我希望它返回一个函数指针。我该怎么做 ?我找不到怎么做。你上面说的这个方法我试过了,但是没用。
    • 好答案。但完全是脑残的 C 函数指针语法。
    • 我建议在空括号之间添加“void”关键字,以便编译器可以捕捉到 getFunc() 的调用者可能认为他/她将 int,int 参数提供给真正的功能,而不是 getFunc()。 IE。您希望编译器捕获“getFunc(x,y)”,因为调用者可能想要执行“getFunc()(x,y)”。
    • 可能跑题了,但是使用Clockwise/Spiral Rule评估复杂的函数声明很容易
    【解决方案5】:

    在将一些 C 代码包装在 C++ 类中时,我有与原始海报相同的愿望:从函数返回函数指针,而不诉诸于 typedef'ing 函数指针原型。我遇到了 C++ const 正确性的问题,我认为这是值得分享的,即使它有点离题(C++),但它确实与原始问题直接相关:返回 C 函数指针的语法而不诉诸typedef.

    下面的代码定义了一个类A,它存储了一个函数指针,并通过get_f()调用将它暴露给外界。这是应该返回没有typedef 的函数指针的函数。

    重点(困扰了我一段时间)是如何声明 get_f() 是一个 const 函数,即它不会改变 A

    代码包含 2 个变体:第一个使用 typedef 作为函数指针原型,而第二个将所有内容全部写出。 #if 在两者之间切换。

    #include <iostream>
    
    int my_f(int i)
    {
      return i + 1;
    }
    
    #if 0 // The version using a typedef'ed function pointer
    
    typedef int (*func_t)(int);
    
    class A
    {
    public:
      A(func_t f) : m_f(f) {}
      func_t get_f() const { return m_f; }
    
    private:
      func_t m_f;
    };
    
    int main(int argc, char *argv[])
    {
      const A a(my_f);
      std::cout << "result = " << a.get_f()(2) << std::endl;
    }
    
    #else // The version using explicitly prototyped function pointer    
    
    class A
    {
    public:
      A(int (*f)(int)) : m_f(f) {}
      int (*get_f() const)(int) { return m_f; }
    
    private:
      int (*m_f)(int);
    };
    
    int main(int argc, char *argv[])
    {
      const A a(my_f);
      std::cout << "result = " << a.get_f()(2) << std::endl;
    }
    
    #endif
    

    预期/期望的输出是:

    result = 3
    

    关键是const限定符在行中的位置:

    int (*get_f() const)(int) { return m_f; }
    

    【讨论】:

      【解决方案6】:

      这是一个愚蠢的例子,但它很简单而且不会出错。这只是声明静态函数:

      #include <stdio.h>
      #include <stdlib.h>
      
      void * asdf(int);
      static int * hjkl(char,float);
      
      main() {
        int a = 0;
        asdf(a);
       }
      
      
      void * asdf(int a) {return (void *)hjkl; }
      static int * hjkl(char a, float b) {int * c; return c;}
      

      【讨论】:

      • C 标准没有定义将指向数据的指针转换为指向函数的指针的行为。此外,这并不比 OP 的示例简单。
      • 实际上他并没有将指向数据的指针转换为指向函数的指针。他有一个指向函数的指针,他正在转换为 void* 然后将其转换回函数。这是有效的,事实上 void* 返回类型是 GNU 的 dlsym 函数的工作方式,问题是,它基本上是一种我试图避免的弱类型
      【解决方案7】:

      我认为你有三个选择:

      1. 坚持使用 typedef。归根结底,这是 typedef 的工作。
      2. 返回 void* 并对其进行强制转换。
      3. 重新考虑您的软件架构。也许您可以与我们分享您正在努力实现的目标,看看我们能否为您指明更好的方向。

      【讨论】:

      • 请注意,void * 与函数指针不(必然)兼容。
      • 指向 void 的指针是指向对象类型的指针,C 标准没有定义将指向对象类型的指针转​​换为指向函数类型的指针的行为,反之亦然。您可以将指向函数类型的指针转​​换为指向另一个函数类型的指针,只要在使用前将其转换为兼容类型即可。
      • 我目前并没有尝试实现任何具体的目标,这只是我在执行诸如使用 libld 跨多个版本动态链接到共享库之类的事情时偶尔会遇到的问题
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2023-02-04
      • 2021-05-30
      • 1970-01-01
      • 2012-06-07
      • 1970-01-01
      • 1970-01-01
      • 2018-04-06
      相关资源
      最近更新 更多