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)
所述void
s时,可以省略,在这种情况下,函数指针指向需要未知数目的参数的函数。这不是您想要的。要声明指向不带参数的函数的函数指针,应void
在函数参数列表内添加。最好以相同的方式更改get_pfn
为void (*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)
该函数的返回类型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中键入此内容来进行验证
没有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)