是否可以声明一些函数类型func_t
,使其返回该类型func_t
?
换句话说,一个函数是否能够返回自身?
// func_t is declared as some sort of function pointer
func_t foo(void *arg)
{
return &foo;
}
或者我必须使用 void *
并进行类型转换吗?
是否可以声明一些函数类型func_t
,使其返回该类型func_t
?
换句话说,一个函数是否能够返回自身?
// func_t is declared as some sort of function pointer
func_t foo(void *arg)
{
return &foo;
}
或者我必须使用 void *
并进行类型转换吗?
使用结构体的可能解决方案:
struct func_wrap
{
struct func_wrap (*func)(void);
};
struct func_wrap func_test(void)
{
struct func_wrap self;
self.func = func_test;
return self;
}
使用gcc -Wall
编译时没有警告,但我不确定是否100%可移植。
gcc -Wall -Werror -Wextra -pedantic -c func.c -std=c89
编译func.c没有问题。 - panzi不,您不能在C语言中声明递归函数类型。除了在结构体(或联合体)中,C语言并不支持声明递归类型。
至于使用 void *
的解决方案,void *
仅保证保存对象指针而非函数指针。将函数指针转换为 void *
只作为一种扩展提供。
state_machine
对象的函数,其中包含一个指向函数的指针,类型为 struct state_machine (*fp)(args)
。然后,函数 foo
可以使用以下代码“返回自身”:struct state_machine ret; ret.fp = foo; ... return ret;
- torekvoid (*the_most_pointless_function_in_the_world(void))(void){ return the_most_pointless_function_in_the_world; }
?这个函数有趣的地方在于它确实返回了自己,调用 the_most_pointless_function_in_the_world();
会返回这个函数,如果把它赋值给一个变量,那么这个变量也可以被调用,但是 the_most_pointless_function_in_the_world()();
会导致编译错误。我想我把C语言玩过头了... - Braden Best你不能将函数指针转换为void*
(它们可能具有不同的大小),但这并不是问题,因为我们可以将其转换为另一种函数指针类型,然后再次转换以获取原始值。
typedef void (*fun2)();
typedef fun2 (*fun1)();
fun2 rec_fun()
{
puts("Called a function");
return (fun2)rec_fun;
}
// later in code...
fun1 fp = (fun1)((fun1)rec_fun())();
fp();
输出:
Called a function
Called a function
Called a function
T f(void)
{
return &f;
}
f()
返回类型为 T
的值,但表达式 &f
的类型是“返回类型为 T
的函数指针”。无论 T
是什么,表达式 &f
总是不同的、不兼容的类型 T (*)(void)
。即使 T
是指向函数的指针类型,例如 Q (*)(void)
,表达式 &f
最终将成为“返回指向函数的指针的函数指针”,或者 Q (*(*)(void))(void)
。
如果 T
是足够大以容纳函数指针值的整数类型,并且在您的平台上从 T (*)(void)
到 T
再到 T (*)(void)
的转换有意义,那么您可能可以像下面这样做:
T f(void)
{
return (T) &f;
}
函数不可能通过值返回自身。但是,它可以通过指针返回自身。
C语言允许定义接受未定义数量参数的函数类型,并且这些类型与接受已定义参数的函数类型兼容。
例如:
typedef void fun_t();
void foo(int);
fun_t *fun = foo; // types are fine
因此,以下函数将起作用。
void fun(void (**ptr)()) {
*ptr = &fun;
}
以下是示例用法:
#include <stdio.h>
void fun(void (**ptr)()) {
puts("fun() called");
*ptr = &fun;
}
int main() {
void (*fp)();
fun(&fp); /* call fun directly */
fp(&fp); /* call fun indirectly */
return 0;
}
该代码在C89标准下以严格模式编译,没有任何警告。
它产生了预期的输出:
fun() called
fun() called
#include <stdio.h>
#include <stdint.h>
#include <stdlib.h>
typedef void *(*fptr)(int *);
void *start (int *);
void *stop (int *);
void *start (int *a) {
printf("%s\n", __func__);
return stop(a);
}
void *stop (int *a) {
printf("%s\n", __func__);
return start(a);
}
int main (void) {
int a = 10;
fptr f = start;
f(&a);
return 0;
}
这样怎么样:
typedef void* (*takesDoubleReturnsVoidPtr)(double);
void* functionB(double d)
{
printf("here is a function %f",d);
return NULL;
}
takesDoubleReturnsVoidPtr functionA()
{
return functionB;
}
int main(int argc, const char * argv[])
{
takesDoubleReturnsVoidPtr func = functionA();
func(56.7);
return 0;
}
if (someCondition) return functionA else return functionB;
。 - Drew McGowentypedef id (*IMP)(id, SEL, ...);
的东西,因为 IMP 返回一个抽象对象 id
,该对象可以包含其自己的 IMP
,因此您可以采用面向对象的方法。 - Grady Player有一种方法,你可以尝试这个:
typedef void *(*FuncPtr)();
void *f() { return f; }
int main() {
FuncPtr f1 = f();
FuncPtr f2 = f1();
FuncPtr f3 = f2();
return 0;
}
void *
到函数指针的转换不是标准的,也绝对不是隐式的。 - Antti Haapala -- Слава Україніlet rec f () = f;;
,其类型将被推断为unit -> 'a as 'a
。但是因为他既没有标记问题为C ++也没有标记为OCaml,所以我们并没有真正地提供帮助,是吗? - Pascal Cuoq