定义一个函数,它 returns 一个函数指针,它也是 returns 一个没有 typedef 的函数指针
Defining a function which returns a function pointer which also returns a function pointer without typedefs
我试图在不使用 typedef
的情况下真正理解函数指针,但似乎无法理解。我不明白需要什么签名来传达我 return 指向函数指针的指针。
#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__
必须是什么?
是这样的:
void (*(*get_pfn_pfn(void))(int))()
函数 get_pfn
的 return 类型是 -
void (*) ();
所以 &get_pfn
的类型是 -
void (*(*)(int))()
现在,这个函数 return 是这种类型,因此它的签名将是 -
void (*(*(foo)())(int))()
您可以通过在 cdecl.org
中输入来验证这一点
它必须 return 一个函数指针指向一个接受 int
和 return 函数指针的函数:
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 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;
}
没有 typedef
的函数指针可能很难处理。要弄清楚它们,您需要从内到外工作。
那么让我们详细分析一下我们是如何得出正确的函数签名的。
get_pfn_pfn
是一个函数:
get_pfn_pfn()
不带参数:
get_pfn_pfn(void)
和returns一个指针:
*get_pfn_pfn(void)
到一个函数:
(*get_pfn_pfn(void))()
需要一个 int
参数:
(*get_pfn_pfn(void))(int)
和returns一个指针:
*(*get_pfn_pfn(void))(int)
到一个函数:
(*(*get_pfn_pfn(void))(int))()
不带参数:
(*(*get_pfn_pfn(void))(int))(void)
而returns什么都没有(即void
):
void (*(*get_pfn_pfn(void))(int))(void)
当然,使用 typedef
可以大大简化这一过程。
首先是 even
和 odd
的类型:
typedef void (*func1)(void);
然后我们可以将其应用于 get_pfn
:
func1 get_pfn(int) { ... }
那么这个函数的类型:
typedef func1 (*func2)(int);
我们可以申请get_pfn_pfn
:
func2 get_pfn_pfn(void) { ... }
我试图在不使用 typedef
的情况下真正理解函数指针,但似乎无法理解。我不明白需要什么签名来传达我 return 指向函数指针的指针。
#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__
必须是什么?
是这样的:
void (*(*get_pfn_pfn(void))(int))()
函数 get_pfn
的 return 类型是 -
void (*) ();
所以 &get_pfn
的类型是 -
void (*(*)(int))()
现在,这个函数 return 是这种类型,因此它的签名将是 -
void (*(*(foo)())(int))()
您可以通过在 cdecl.org
中输入来验证这一点它必须 return 一个函数指针指向一个接受 int
和 return 函数指针的函数:
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 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;
}
没有 typedef
的函数指针可能很难处理。要弄清楚它们,您需要从内到外工作。
那么让我们详细分析一下我们是如何得出正确的函数签名的。
get_pfn_pfn
是一个函数:
get_pfn_pfn()
不带参数:
get_pfn_pfn(void)
和returns一个指针:
*get_pfn_pfn(void)
到一个函数:
(*get_pfn_pfn(void))()
需要一个 int
参数:
(*get_pfn_pfn(void))(int)
和returns一个指针:
*(*get_pfn_pfn(void))(int)
到一个函数:
(*(*get_pfn_pfn(void))(int))()
不带参数:
(*(*get_pfn_pfn(void))(int))(void)
而returns什么都没有(即void
):
void (*(*get_pfn_pfn(void))(int))(void)
当然,使用 typedef
可以大大简化这一过程。
首先是 even
和 odd
的类型:
typedef void (*func1)(void);
然后我们可以将其应用于 get_pfn
:
func1 get_pfn(int) { ... }
那么这个函数的类型:
typedef func1 (*func2)(int);
我们可以申请get_pfn_pfn
:
func2 get_pfn_pfn(void) { ... }