Рекурсивное объявление указателя на функцию в C - PullRequest
20 голосов
/ 27 апреля 2009

Я хотел бы объявить функцию, которая возвращает указатель на функцию того же типа.

Я хотел бы использовать его для реализации конечных автоматов, как показано ниже:

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

Мне удается обойти ошибку компиляции, используя следующие структуры:

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

Но это усложняет возврат:

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

Интересно, есть ли лучший способ создания таких указателей на функции в c.

Ответы [ 2 ]

8 голосов
/ 27 апреля 2009

Это невозможно сделать в C: функция не может возвращать указатель на себя, так как объявление типа расширяется рекурсивно и никогда не заканчивается. См. Эту страницу для объяснения: http://www.gotw.ca/gotw/057.htm

Обходной путь, описанный на приведенной выше странице, означает возврат void (*) () вместо правильно набранного указателя функции; ваш обходной путь, возможно, немного аккуратнее.

2 голосов
/ 27 апреля 2009

Это обсуждается в книге Херба Саттера Подробнее Исключительно C ++ , пункт 32, где кажется, что ответ (для C) "не без использования приведений". Для C ++ это возможно с обычным введением класса, чтобы обеспечить некоторую дополнительную косвенность.

...