如何声明指向返回函数指针的函数的指针?

3

以下代码正常运行并输出预期结果。 我有一个额外的问题,如何在我的主函数中声明一个指针,它保存函数A(funcA)的地址?

#include<stdio.h>
#include<stdlib.h>


int funcB (void)
{
 printf("\n Now you are in function B \n ");

 printf ("\n this function is for returning code value no matter what\n");

 return -10;
}

int (*funcA(int x,int y)) (void)
{
 printf( " I am in function A \n ");
   static int sum;
   sum=x+y;
 printf ( "\n Sum is %d ",sum);
 return &funcB;
 }

int main ()

{

int (*fpb)(void);

int x;

fpb=funcA(10,15);

x=(*fpb)();   // Calling function B through fpb pointer

printf("\n Value stored in x for code is %d \n",x);

}

结果

我在函数A中
总和为25 现在你在函数B中
这个函数是用来返回代码值的,无论如何
存储在x中的代码值为-10

以下代码有效,(很高兴知道有不同的指针声明选项,其中一些非常容易,现在可以通过auto关键字实现)。我正在声明fpa指向函数A的指针。幸运的是,我发现fpa和fpb的语法是相同的。 int (*fpa) (void); fpa = funcA(100,200); - theartist33
不要尝试编写多语言源文件。这是非常困难的工作,与编写单语言源文件(各种文件而不是一个文件)相比,任何可能的优势都非常非常小。 - pmg
7个回答

4
在我的主函数中,我该如何声明一个指针,使其保存函数A(funcA)的地址?
  1. 您可以直接编写它(并且不太美观):

    int (*(*fpa)(int,int)) (void) = &funcA;

  2. 您可以使用typedef使其更清晰:

    typedef int (*FPB)(void);
    typedef FPB (*FPA)(int, int);
    FPA fpa = &funcA;

  3. 因为您标记了c ++,所以您可以使用auto specifier(自c ++11起)使其直接和清晰:

    auto fpa = &funcA;


@songyuanyao:我也同意,只是要提一下,它应该是typedef int (FPB) (void);。 - theartist33
@theartist33 *是必要的,以使其成为函数指针类型。演示 - songyuanyao
@songyuanyao:可能是这样,但就这个原始代码而言,我不想让funcB返回任何地址,它只是一个简单的int (fpb) (void),我检查了它的工作方式,以你所说的*funcB为typedef声明它并没有抛出错误,但运行时出现了内存故障。 - theartist33
@theartist33 我在这里尝试了一下(http://rextester.com/IYJC22326)。运行时错误可能是其他问题。 - songyuanyao
@theartist33 我明白了,你正在使用 fa *fpa,没问题。 - songyuanyao

3
语法够生涩,最好使用typedef。我不假设使用C++11。()放在*NameOfType周围。
typedef int (*funcBTypePointer) (void);

int main ()
{
    funcBTypePointer fpb;

    ...
}

我看到funcA的返回值是funcB的地址。下面是如何实现这个功能的:

funcBTypePointer funcA(int x,int y)
{
 printf( " I am in function A \n ");
 static int sum;
 sum=x+y;
 printf ( "\n Sum is %d ",sum);
 return funcB;
}

如果您引用一个没有参数列表的函数,您将获得该函数的指针;不需要使用&
有关函数指针的更多信息,请参阅此教程:http://www.learncpp.com/cpp-tutorial/78-function-pointers/

2
为了确定指向funcA的指针类型,需要查看funcA的声明:
int (*funcA(int x,int y)) (void)

funcA 替换为 (*fptr),这样你的声明就变成了

int (*(*fptr)(int x, int y))(void);

这被解读为

        fptr                          -- fptr
       *fptr                          -- is a pointer
      (*fptr)(            )           -- to a function with
      (*fptr)(    x,      )           -- parameter x
      (*fptr)(int x,      )           --   is an int
      (*fptr)(int x,     y)           -- parameter y
      (*fptr)(int x, int y)           --   is an int
     *(*fptr)(int x, int y)           -- returning a pointer
    (*(*fptr)(int x, int y))(    )    -- to a function with
    (*(*fptr)(int x, int y))(void)    -- no parameters
int (*(*fptr)(int x, int y))(void);   -- returning int

你需要将其分配为:
fptr = funcA;

并将其称为

int x = (*(*fptr)(a,b))();

请注意,虽然我们中的一些人认为这种声明是1非常清晰明了的,但大多数C程序员并不会过度关注声明语法,并倾向于通过typedef隐藏大部分复杂性:

typedef int fb(void);
typedef fb *fa(int x, int y);

fa *fptr = funcA;

然而,这个声明并没有告诉你如何在表达式中使用fptr,同时保留HTML标签。
int (*(*fptr)(int x, int y))(void);

非常明确:

int x = (*(*fptr)(a,b))();


1. 我很乐意承认在这方面我是个异常者;我曾经写过一些代码,几乎和上面的 fptr 调用一样(即,在一个表达式中通过指针调用多个函数),并且认为它非常清晰明了。但我的同事们很快提醒我说我很奇怪,并坚持要求我将其分解成单独的语句。


我尝试按照您上面写的方式使用下面的代码,但编译时出现了“参数过多”的错误:int (*(*fpa)(int,int))(void)=NULL; int t=(*(*fpa)(10,30))(void); - theartist33
@theartist33:抱歉,我在函数“调用”中遗漏了 void 关键字,这也是错误的来源;它应该是 int t = (*(*fpa)(10,30))();。这就是因为我没有测试我所写的内容而导致的。我会修正我的回答。 - John Bode

1
声明“指向函数的指针”的第一条规则是“使用typedef”。两周后回来尝试弄清楚到底发生了什么,你会感激不尽。
typedef void (*pfuncB_t)();  // (void) is a C-compatability hack.  Use () in C++.

所以funcA的声明变得更容易阅读了:
pfuncB_t funcA(int x, int y);

声明一个指向funcA函数的指针类型也很容易。

typedef pfuncB_t (*pfuncA_t)(int, int);

你可以这样使用它:

pfuncA_t globalA = &funcA;   // You don't need the address-of, but it is legal.

1

如何声明一个指针,可以保存到 funcA 的指针?

除非你非常勇敢(而我懒得那么勇敢),你可以使用指向 FuncB 类型的指针的 typedef

typedef int (*FunctionReturningInt)(void);

现在,funcA 是一个返回 FunctionReturningInt 的函数:
extern FunctionReturningInt funcA(int x, int y);

创建指向那个内容的指针:
FunctionReturningInt (*funcA_ptr)(int x, int y) = funcA;

1
这就是“勇敢”的“是的,部长”意义。请参见http://c2.com/cgi/wiki?YesMinisterCourageValue - Martin Bonner supports Monica

1
使用几个 typedef
#include <stdio.h>
#include <stdlib.h>

int funcB(void) {
    printf("Now you are in function B\n");
    printf("this function is for returning code value no matter what\n");
    return -10;
}

int (*funcA(int x,int y)) (void) {
    printf("I am in function A\n");
    static int sum;
    sum = x + y;
    printf("Sum is %d\n", sum);
    return &funcB;
}

// typedefs to make life easier    
typedef int (ta)(void);
typedef ta *(tb)(int, int); // use previous typedef'd ta

int main(void) {
    int x, y;
    ta *fpb;
    tb *fpa;

    fpb = funcA(10, 15);
    fpa = funcA;
    x = fpb();   // Calling function B through fpb pointer
    y = fpa(10, 15)(); // calling function B through pointer to function A

    printf("Value stored in x for code is %d\n", x);
    printf("Value stored in y for code is %d\n", y);

    return 0;
}

1
值得一提的是,您也可以使用 std::function(c++11)来进行编程。然而,这不是函数指针,而是一个可以容纳任何可调用对象的包装器。与简单指针相比,这是一种更加繁重的方法。如果函数指针足以满足您的要求并且您不需要管理很多函数,则我绝对建议您使用函数指针。

(http://en.cppreference.com/w/cpp/utility/functional/function)

#include <cstdio>
#include <cstdlib>
#include <functional>


int funcB()
{
  printf("\n Now you are in function B \n ");
  printf("\n this function is for returning code value no matter what\n");
  return -10;
}

std::function<int(void)> funcA(int x, int y)
{
  printf(" I am in function A \n ");
  static int sum;
  sum = x + y;
  printf("\n Sum is %d ", sum);
  return funcB;
}

int main()
{
  std::function<std::function<int(void)>(int, int)> func_a = funcA;
  std::function<int(void)> func_b = func_a(10, 15);
  int x = func_b();

  printf("\n Value stored in x for code is %d \n", x);

  return 0;
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接