Función que se devuelve

¿Es posible declarar algún tipo de función func_t que devuelve ese tipo, func_t ?

En otras palabras, ¿es posible que una función se devuelva?

 // func_t is declared as some sort of function pointer func_t foo(void *arg) { return &foo; } 

¿O tendría que usar void * y typecasting?

No, no puede declarar tipos de funciones recursivas en C. Excepto dentro de una estructura (o una unión), no es posible declarar un tipo recursivo en C.

Ahora, para la solución void * , void * solo garantiza punteros a objetos y no punteros a funciones. Poder convertir punteros de función y void * está disponible solo como una extensión.

Una posible solución con estructuras:

 struct func_wrap { struct func_wrap (*func)(void); }; struct func_wrap func_test(void) { struct func_wrap self; self.func = func_test; return self; } 

Comstackndo con gcc -Wall no dio ninguna advertencia, pero no estoy seguro si esto es 100% portátil.

No puede convertir punteros a la función void* (pueden ser de diferentes tamaños), pero eso no es un problema, ya que podemos convertir a otro tipo de puntero a función y devolverlo para obtener el valor original.

 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(); 

Salida:

 Called a function Called a function Called a function 

En otras palabras, ¿es posible que una función se devuelva?

Depende de lo que quiere decir con “sí mismo”; si te refieres a un puntero a sí mismo, ¡la respuesta es sí! Si bien no es posible que una función devuelva su tipo, una función puede devolver un puntero a sí misma y este puntero puede convertirse al tipo apropiado antes de llamar.

Los detalles se explican en la pregunta comp.lang.c faq: Función que puede devolver un puntero a una función del mismo tipo.

Verifique mi respuesta para más detalles.

¿Qué tal algo así?

 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; } 

Asumir la definición de la función

 T f(void) { return &f; } 

f() devuelve un valor de tipo T , pero el tipo de la expresión &f es “puntero a la función que devuelve T “. No importa qué es T , la expresión &f siempre será de un tipo incompatible diferente, T (*)(void) . Incluso si T es un tipo de puntero a función tal como Q (*)(void) , la expresión &f terminará siendo “puntero-a-función-retornando-puntero-a-función”, o Q (*(*)(void))(void) .

Si T es un tipo integral que es lo suficientemente grande como para contener un valor de puntero de función y la conversión de T (*)(void) a T y de regreso a T (*)(void) es significativo en su plataforma, es posible que pueda escaparse con algo así como

 T f(void) { return (T) &f; } 

pero puedo pensar en al menos un par de situaciones en las que eso no funcionará en absoluto. Y, sinceramente, su utilidad sería extremadamente limitada en comparación con el uso de algo así como una tabla de búsqueda.

C simplemente no fue diseñado para tratar funciones como cualquier otro elemento de datos, y los punteros a las funciones no son intercambiables con los punteros a los tipos de objetos.

Hay una manera, solo intenta esto:

 typedef void *(*FuncPtr)(); void *f() { return f; } int main() { FuncPtr f1 = f(); FuncPtr f2 = f1(); FuncPtr f3 = f2(); return 0; } 

Si estuviera usando C ++, podría crear un tipo de objeto de State (suponiendo el uso de ejemplo de máquina de estado) en el que declare un operator() que devuelve un tipo de objeto de State por referencia o puntero. A continuación, puede definir cada estado como una clase de State derivada que devuelve cada otro tipo derivado apropiado de su implementación de operator() .