定义一个函数,该函数返回一个函数指针,该函数指针也返回一个不带typedef的函数指针

时间:2019-09-10 17:05:52

标签: c function function-pointers

我正在尝试不使用typedef来真正理解函数指针,但是似乎无法理解。我不知道传达一个指向函数的指针需要传达什么签名。

#include <stdio.h>

void odd()  { printf("odd!\n");  }
void even() { printf("even!\n"); }

void (*get_pfn(int i))()
{
    return i % 2 == 0 ? &even : &odd;
}

__SIGNATURE__
{
    return &get_pfn;
}

int main()
{
    get_pfn_pfn()(1)();
    get_pfn_pfn()(2)();
    return 0;
}

要使这项工作有效,__SIGNATURE__必须是什么?

4 个答案:

答案 0 :(得分:21)

它必须返回一个函数指针,该函数指针需要一个int并返回一个函数指针:

void (*(*get_pfn_pfn(void))(int))(void) {
    return &get_pfn;
}

更多行:

void (*
        (*
             get_pfn_pfn(void)  // this is our function
        )(int i) // this is get_pfn(int)
     )(void)  // this is odd() or even()
{
    return &get_pfn;
}

void可以省略,在这种情况下,函数指针指向带有未知数量参数的函数。这不是您想要的。要声明指向不带参数的函数的函数指针,应在函数参数列表内添加void。同样,最好将get_pfn更改为void (*get_pfn(int i))(void)。例如,尝试从get_pfn(1)("some arg", "some other arg");进行呼叫。 C编译器不会发出警告,因为空()表示 unknown 参数。要说该函数不带参数,您必须(void)

对于许多大括号序列,尤其是))(,函数指针很难解析。这就是为什么许多人倾向于使用typedef作为函数指针或类型的原因:

typedef void get_pfn_func_t(void);    
get_pfn_func_t *get_pfn(int i) {
    return i % 2 == 0 ? &even : &odd;
}

typedef get_pfn_func_t *get_pfn_pfn_func_t(int i);
get_pfn_pfn_func_t *get_pfn_pfn(void) {
    return &get_pfn;
}

答案 1 :(得分:7)

函数get_pfn的返回类型为-

void (*) ();

所以&get_pfn的类型是-

void (*(*)(int))()

现在,此函数返回此类型,因此其签名为-

void (*(*(foo)())(int))()

您可以通过在cdecl.org中输入

来进行验证

答案 2 :(得分:6)

不带typedef的函数指针可能很难使用。要弄清楚它们,您需要由内而外地进行工作。

因此,让我们准确地分解出我们如何得出正确的函数签名。

get_pfn_pfn是一个功能:

get_pfn_pfn()

不使用任何参数:

get_pfn_pfn(void)

并返回一个指针:

*get_pfn_pfn(void)

功能:

(*get_pfn_pfn(void))()

哪个带有int参数:

(*get_pfn_pfn(void))(int)

并返回一个指针:

*(*get_pfn_pfn(void))(int)

功能:

(*(*get_pfn_pfn(void))(int))()

不使用任何参数:

(*(*get_pfn_pfn(void))(int))(void)

并且不返回任何内容(即void):

void (*(*get_pfn_pfn(void))(int))(void)

当然,使用typedef可以大大简化这一过程。

首先,evenodd的类型:

typedef void (*func1)(void);

然后我们可以将其应用于get_pfn

func1 get_pfn(int) { ... }

然后输入此函数的类型:

typedef func1 (*func2)(int);

我们可以将其应用于get_pfn_pfn

func2 get_pfn_pfn(void) { ... }

答案 3 :(得分:1)

是这样的:

void (*(*get_pfn_pfn(void))(int))()
相关问题