Как объявить указатель функции, который возвращает указатель на функцию
Как вы объявляете указатель на функцию, которая указывает на функцию с теми же параметрами, а также возвращает указатель на функцию с теми же параметрами.
т.е. funcPtr
указывает на func1(int a, int b)
, а func1
возвращает указатель на другую функцию func2(int a, int b)
. func2
также возвращает указатель на функцию с той же сигнатурой, что и func1
.
TYPE funcPtr = func1;
funcPtr = funcPtr(0, 1);
Как объявить funcPtr
? Каким должен быть TYPE
?
Ответы
Ответ 1
Неразрешимая самооценка
Это невозможно напрямую. Если вы попытаетесь определить тип указателя функции, в котором тип возвращаемой функции будет свой собственный тип, вы столкнетесь с неразрешенной самореференцией, и для этого потребуется бесконечная рекурсия.
typedef funcType (*funcType)(void);
Вернуть struct
Вместо этого вы можете объявить, что функция возвращает структуру, а структура может содержать указатель на такую функцию.
struct func {
struct func (*func) (void);
};
struct func foo (void);
struct func bar (void);
struct func foo (void) { return (struct func){ bar }; }
struct func bar (void) { return (struct func){ foo }; }
...
struct func funcPtr = { foo };
funcPtr = funcPtr.func();
Возвращает другой тип указателя функции
Если вы предпочитаете придерживаться строго указателей, вам нужно прибегнуть к определению функций, которые возвращают другой тип указателя функции. Таким образом, результат вызова должен быть возвращен к правильному типу указателя перед вызовом.
typedef void (*funcPtrType)(void);
typedef funcPtrType funcType(void);
funcType foo;
funcType bar;
funcPtrType foo (void) { return (funcPtrType)bar; }
funcPtrType bar (void) { return (funcPtrType)foo; }
...
funcType *p = foo;
p = (funcType *)p();
Возврат индекса †
Вместо этого вы можете определить свои функции, чтобы вернуть индекс в таблицу, которая представляет функцию, которая должна быть вызвана.
enum funcEnum { fooEnum, barEnum };
typedef enum funcEnum (*funcType)(void);
enum funcEnum foo (void) { return barEnum; }
enum funcEnum bar (void) { return fooEnum; }
funcType funcTable[] = { [fooEnum] = foo, [barEnum] = bar };
...
funcType p = funcTable[fooEnum];
p = funcTable[p()];
† Это было поднято в комментариях и в ответе Павла, но представлено здесь для полноты.
Ответ 2
Это только пример без typedefs. Вы можете попытаться изменить параметры функций, но синтаксис ужасен и обычно бесполезен.
char (*(*((*foo)()))())()
foo - указатель на функцию, возвращающую указатель на функцию, возвращающую указатель на функцию, возвращающую символ
Или вы можете использовать typedefs
например
typedef int (*foo2)(int, int);
typedef foo2 (*foo1)(int, int);
typedef foo1 (*foo)(int, int);
или более общий
typedef int (*foo'n')(int, int);
typedef foo'n' (*foo'n-1')(int, int);
...
typedef foo2 (*foo1)(int, int);
typedef foo1 (*foo)(int, int);
Ответ 3
Я думаю, что настоящая проблема в C заключается в том, что вы получаете бесконечное объявление, поскольку функция возвращает указатель на функцию, и этот указатель функции нужно ввести, чтобы вернуть указатель функции, который необходимо ввести в....
Ниже приведено несколько шагов в таком бесконечном объявлении, чтобы показать, как декларация расширяется и расширяется:
int f0(int a) {
return 1;
}
int (*f1(int a))(int) {
return f0;
}
int (*(*f2(int a))(int))(int) {
return f1;
}
В качестве решения для устаревшего кода он может возвращать номер состояния, а таблица с функциями может использоваться для вызова функции, определенной для состояния, например: #define STATE0 0
#define STATE1 1
int fx1(int a);
int fx2(int a);
int (*ftab[])(int) = {
fx1,
fx2
};
void examplefunc(void)
{
int x = ftab[STATE1](3); // example of calling function from table
}