C указатель на функцию с неопределенной сигнатурой

Я намерен объяснить стандартное доказательство теоремы о рекурсии на C, используя факториал в качестве примера. Так что я

#include <stdio.h>

typedef unsigned Nat;
typedef Nat Func();

Nat G(Nat n, Func f){
    if(n) return n * f(n-1, f);
    else return 1;
}

int main(void){
    printf("%u", G(5, G));
    return 0;
}

Он работает (печатает 120) на каждом компиляторе, который я смог найти, но меня беспокоит то, что я передаю указатель на функцию в параметр, который на самом деле не имеет полностью определенного типа (это функция, возвращающая Nat, но типы параметров не указаны). Это нормально по стандарту (любой стандарт, но желательно тот, который не поддерживает неуказанные типы параметров, так что я думаю, C89:)?

Конечно, я хотел бы еще больше иметь возможность полностью указать Func, но это кажется невозможным (очевидный способ,

typedef Nat Func(Nat, Func);

не работает).

1 ответ

Это не так красиво, но вы можете иметь полностью определенный тип, если заключите его в структуру.

#include <stdio.h>

typedef unsigned Nat;
typedef struct wrapped_Func Func;
struct wrapped_Func {
  Nat (*call)(Nat, Func);
};
#define FUNC(f) ((struct wrapped_Func){.call=f})

static Nat G(Nat n, Func f){
    if(n) return n * f.call(n-1, f);
    else return 1;
}

int main(void){
    printf("%u\n", G(5, FUNC(G)));
    return 0;
}

(Структура литерала в FUNC макрос - это особенность C99. в С89 будет еще страшнее.)

Другие вопросы по тегам