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

Jas*_*Jas 19 c function-pointers function

我试图不使用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;
}
Run Code Online (Sandbox Code Playgroud)

为了使这项工作,__SIGNATURE__必须做什么?

Kam*_*Cuk 21

它必须返回一个函数指针,该函数指针采用a int并返回一个函数指针:

void (*(*get_pfn_pfn(void))(int))(void) {
    return &get_pfn;
}
Run Code Online (Sandbox Code Playgroud)

更多行:

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;
}
Run Code Online (Sandbox Code Playgroud)

所述voids时,可以省略,在这种情况下,函数指针指向需要未知数目的参数的函数。这不是您想要的。要声明指向不带参数的函数的函数指针,应void在函数参数列表内添加。最好以相同的方式更改get_pfnvoid (*get_pfn(int i))(void)。例如,尝试从拨打电话get_pfn(1)("some arg", "some other arg");。AC编译器不会发出警告,因为空()表示未知参数。要说该函数不带参数,您必须(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;
}
Run Code Online (Sandbox Code Playgroud)

  • 这证实可以与在线C检查一起使用。 (4认同)

Aja*_*iya 7

该函数的返回类型get_pfn是-

void (*) ();
Run Code Online (Sandbox Code Playgroud)

所以类型&get_pfn是-

void (*(*)(int))()
Run Code Online (Sandbox Code Playgroud)

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

void (*(*(foo)())(int))()
Run Code Online (Sandbox Code Playgroud)

您可以通过在cdecl.org中键入此内容来进行验证


dbu*_*ush 6

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

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

get_pfn_pfn 是一个功能:

get_pfn_pfn()
Run Code Online (Sandbox Code Playgroud)

不带任何参数:

get_pfn_pfn(void)
Run Code Online (Sandbox Code Playgroud)

并返回一个指针:

*get_pfn_pfn(void)
Run Code Online (Sandbox Code Playgroud)

要功能:

(*get_pfn_pfn(void))()
Run Code Online (Sandbox Code Playgroud)

它带有一个int参数:

(*get_pfn_pfn(void))(int)
Run Code Online (Sandbox Code Playgroud)

并返回一个指针:

*(*get_pfn_pfn(void))(int)
Run Code Online (Sandbox Code Playgroud)

要功能:

(*(*get_pfn_pfn(void))(int))()
Run Code Online (Sandbox Code Playgroud)

不带任何参数:

(*(*get_pfn_pfn(void))(int))(void)
Run Code Online (Sandbox Code Playgroud)

并不返回任何值(即void):

void (*(*get_pfn_pfn(void))(int))(void)
Run Code Online (Sandbox Code Playgroud)

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

首先输入even和的类型odd

typedef void (*func1)(void);
Run Code Online (Sandbox Code Playgroud)

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

func1 get_pfn(int) { ... }
Run Code Online (Sandbox Code Playgroud)

然后,此函数的类型:

typedef func1 (*func2)(int);
Run Code Online (Sandbox Code Playgroud)

我们可以申请get_pfn_pfn

func2 get_pfn_pfn(void) { ... }
Run Code Online (Sandbox Code Playgroud)