Declaración recursiva del puntero de función en C

2 minutos de lectura

avatar de usuario
Piotr Czapla

Me gustaría declarar una función que devuelva un puntero a una función del mismo tipo.

Me gustaría usarlo para implementar máquinas de estado como la siguiente:

typedef event_handler_t (*event_handler_t)(event_t*); // compilation error

event_handler_t state2(event_t* e);
event_handler_t state1(event_t* e) {
    switch(e->type) {
    //...
    case SOME_EVENT:
        return state2;
    //...
    }

}
event_handler_t state2(event_t* e) {
    switch(e->type) {
    //...
    case OTHER_EVENT:
        return state1;
    //...
    }   
}

//...
event_handler_t event_handler;
//...
event_handler(&e);
//...

Me las arreglé para evitar el error de compilación usando estructuras de la siguiente manera:

typedef struct event_handler {
    struct event_handler (*func)(event_t *);
} event_handler_t;

Pero esto hace que la declaración de devolución sea más complicada:

event_handler_t state2(event_t* e) {
{
    event_handler_t next_handler = {NULL};
    switch(e->type) {
    //...
    case OTHER_EVENT:
        next_handler.func = state1;
        break;
    //...
    } 
    return next_handler;
}

Me pregunto si hay una mejor manera de crear tales punteros de función en c.

  • Véase también: SO 816356

    –Jonathan Leffler

    13/10/2013 a las 20:43

avatar de usuario
tim robinson

No es posible hacer esto en C: una función no puede devolver un puntero a sí misma, ya que la declaración de tipo se expande recursivamente y nunca termina. Vea esta página para una explicación: http://www.gotw.ca/gotw/057.htm

La solución alternativa descrita en la página anterior significa volver void (*) () en lugar del puntero de función correctamente escrito; Podría decirse que su solución es un poco más ordenada.

Esto se discute en el libro de Herb Sutter C++ más excepcional, ítem 32, donde la respuesta parece ser (para C) “no sin el uso de moldes”. Para C ++, es posible con la introducción habitual de una clase proporcionar alguna indirección adicional.

¿Ha sido útil esta solución?

Esta web utiliza cookies propias y de terceros para su correcto funcionamiento y para fines analíticos y para mostrarte publicidad relacionada con sus preferencias en base a un perfil elaborado a partir de tus hábitos de navegación. Al hacer clic en el botón Aceptar, acepta el uso de estas tecnologías y el procesamiento de tus datos para estos propósitos. Configurar y más información
Privacidad