c function function-pointers

Definir una función que devuelve un puntero de función que también devuelve un puntero de función sin typedefs



function function-pointers (4)

Estoy tratando de entender realmente los punteros de función sin usar typedef pero parece que no puedo entender esto. No entiendo qué firma se necesita para transmitir que devuelvo un puntero a un puntero a una función.

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

Para que esto funcione, ¿ __SIGNATURE__ tiene que ser __SIGNATURE__ ?


El tipo de retorno de la función get_pfn es -

void (*) ();

Entonces, el tipo de &get_pfn es -

void (*(*)(int))()

Ahora, esta función devuelve este tipo, por lo tanto, su firma será:

void (*(*(foo)())(int))()

Puede verificar esto escribiendo esto en cdecl.org


Los punteros de función sin typedef pueden ser difíciles de trabajar. Para resolverlos, trabajas de adentro hacia afuera.

Analicemos exactamente cómo encontramos la firma de función correcta.

get_pfn_pfn es una función:

get_pfn_pfn()

Que no tiene parámetros:

get_pfn_pfn(void)

Y devuelve un puntero:

*get_pfn_pfn(void)

A una función:

(*get_pfn_pfn(void))()

Que toma un parámetro int :

(*get_pfn_pfn(void))(int)

Y devuelve un puntero:

*(*get_pfn_pfn(void))(int)

A una función:

(*(*get_pfn_pfn(void))(int))()

Que no tiene parámetros:

(*(*get_pfn_pfn(void))(int))(void)

Y no devuelve nada (es decir, void ):

void (*(*get_pfn_pfn(void))(int))(void)

Por supuesto, usar typedef ''s simplifica esto enormemente.

Primero el tipo para even e odd :

typedef void (*func1)(void);

Lo que luego podemos aplicar a get_pfn :

func1 get_pfn(int) { ... }

Entonces el tipo para esta función:

typedef func1 (*func2)(int);

Lo que podemos aplicar a get_pfn_pfn :

func2 get_pfn_pfn(void) { ... }


Tiene que devolver un puntero de función a una función que toma un int y devuelve un puntero de función:

void (*(*get_pfn_pfn(void))(int))(void) { return &get_pfn; }

mas lineas:

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

Se pueden omitir los void , en cuyo caso el puntero de función apunta a una función que toma un número desconocido de parámetros. Que no es lo que quieres. Para declarar un puntero de función a una función que no toma argumentos, debe agregar void dentro de la lista de parámetros de función. De la misma manera, es mejor cambiar get_pfn a void (*get_pfn(int i))(void) . Por ejemplo, intente llamar desde get_pfn(1)("some arg", "some other arg"); . El compilador de CA no dará una advertencia, ya que empty () denota argumentos desconocidos . Para decir que la función no requiere argumentos, debe (void) .

Para muchas secuencias de llaves, especialmente ))( en punteros de función son difíciles de analizar. Por eso muchos prefieren typedefs para punteros de función o tipos:

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


es por aquí:

void (*(*get_pfn_pfn(void))(int))()