2009-04-27 14 views
17

Vorrei dichiarare una funzione che restituisce un puntatore a una funzione dello stesso tipo.Dichiarazione ricorsiva del puntatore funzione in C

vorrei usarlo per implementare macchine a stati come quello qui sotto:

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

riesco a risolvere l'errore compliation utilizzando strutture come segue:

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

Ma questo fa ritorno statment più complicato:

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

Mi chiedo se c'è un modo migliore per creare tali puntatori di funzione in c.

+1

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

risposta

7

Non è possibile farlo in C: una funzione non può restituire un puntatore a se stesso, poiché la dichiarazione del tipo si espande in modo ricorsivo e non termina mai. Vedere questa pagina per una spiegazione: http://www.gotw.ca/gotw/057.htm

La soluzione descritta nella pagina precedente significa restituire void (*)() anziché il puntatore di funzione correttamente digitato; la tua soluzione è probabilmente un po 'più ordinata.

+0

Er, buon punto. –

2

Questo è discusso nel libro di Herb Sutter Altro Eccezionale C++, Elemento 32, in cui la risposta sembra essere (per C) "non senza uso di cast". Per C++ è possibile con la solita introduzione di una classe fornire qualche riferimento indiretto in più.