2009-04-27 6 views
17

Je voudrais déclarer une fonction qui renvoie un pointeur sur une fonction du même type.Déclaration récursive du pointeur de fonction dans C

Je voudrais l'utiliser pour mettre en œuvre des machines d'état comme celui ci-dessous:

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); 
//... 

je parviens à contourner l'erreur de compliation en utilisant des structures comme suit:

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

Mais ce qui rend le retour statment plus compliqué:

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

Je me demande s'il y a une meilleure façon de créer de tels pointeurs de fonction dans c.

+1

Voir aussi: [SO 816356] (http://stackoverflow.com/questions/816356/how-can-i-typedef-a-function-pointer-that-takes-a-function-of-its-own -type-as-an) –

Répondre

7

Il n'est pas possible de faire cela en C: une fonction ne peut pas retourner un pointeur sur lui-même, puisque la déclaration de type se développe récursivement et ne se termine jamais. Voir cette page pour une explication: http://www.gotw.ca/gotw/057.htm

La solution de contournement décrite à la page ci-dessus signifie renvoyer void (*)() au lieu du pointeur de fonction correctement typé; Votre solution de contournement est sans doute un peu plus propre.

+0

Euh, bon point. –

2

Ceci est discuté dans le livre de Herb Sutter Plus Exceptionnel C++, article 32, où la réponse semble être (pour C) "pas sans utilisation de moulages". Pour C++, il est possible avec l'introduction habituelle d'une classe de fournir une certaine indirection supplémentaire.

Questions connexes