Возвращение функции
Можно ли объявить некоторый тип функции func_t
, который возвращает этот тип, func_t
?
Другими словами, возможно ли вернуть функцию?
// func_t is declared as some sort of function pointer
func_t foo(void *arg)
{
return &foo;
}
Или мне пришлось бы использовать void *
и typecasting?
Ответы
Ответ 1
Нет, вы не можете объявлять рекурсивные типы функций в C. За исключением внутри структуры (или объединения), невозможно объявить рекурсивный тип в C.
Теперь для решения void *
void *
гарантируется только сохранение указателей на объекты, а не указателей на функции. Возможность конвертировать указатели функций и void *
доступна только как расширение.
Ответ 2
Возможное решение с structs:
struct func_wrap
{
struct func_wrap (*func)(void);
};
struct func_wrap func_test(void)
{
struct func_wrap self;
self.func = func_test;
return self;
}
Компиляция с gcc -Wall
не выдала никаких предупреждений, но я не уверен, что это на 100% переносимо.
Ответ 3
Вы не можете указывать указатели функций на void*
(они могут быть разных размеров), но это не проблема, поскольку мы можем использовать другой тип указателя функции и отбрасывать его обратно, чтобы получить исходное значение.
typedef void (*fun2)();
typedef fun2 (*fun1)();
fun2 rec_fun()
{
puts("Called a function");
return (fun2)rec_fun;
}
// later in code...
fun1 fp = (fun1)((fun1)rec_fun())();
fp();
Вывод:
Called a function
Called a function
Called a function
Ответ 4
Другими словами, возможно ли вернуть функцию?
Это зависит от того, что вы подразумеваете под "самим собой"; если вы имеете в виду указатель на себя, то ответ да! Хотя функция не может возвращать свой тип, функция может возвращать указатель на себя, и этот указатель затем может быть преобразован в соответствующий тип перед вызовом.
Подробности объясняются в вопросе comp.lang.c faq: Функция, которая может возвращать указатель на функцию того же типа.
Подробнее см. .
Ответ 5
как насчет этого:
typedef void* (*takesDoubleReturnsVoidPtr)(double);
void* functionB(double d)
{
printf("here is a function %f",d);
return NULL;
}
takesDoubleReturnsVoidPtr functionA()
{
return functionB;
}
int main(int argc, const char * argv[])
{
takesDoubleReturnsVoidPtr func = functionA();
func(56.7);
return 0;
}
Ответ 6
Предположим, что определение функции
T f(void)
{
return &f;
}
f()
возвращает значение типа T
, но тип выражения &f
- это "указатель на функцию возврата T
". Не имеет значения, что T
, выражение &f
всегда будет другого, несовместимого типа T (*)(void)
. Даже если T
является типом указателя на функцию, например Q (*)(void)
, выражение &f
завершается как "указатель на функцию-возвращающий-указатель на функцию" или Q (*(*)(void))(void)
.
Если T
является интегральным типом, достаточно большим для хранения значения указателя функции и преобразования от T (*)(void)
до T
и обратно к T (*)(void)
, имеет смысл на вашей платформе, вы можете уйти с что-то вроде
T f(void)
{
return (T) &f;
}
но я могу подумать, по крайней мере, о нескольких ситуациях, когда это не будет работать вообще. И, честно говоря, его утилита будет крайне ограничена по сравнению с использованием чего-то вроде таблицы поиска.
C просто не был предназначен для обработки таких функций, как любой другой элемент данных, а указатели на функции не взаимозаменяемы с указателями на типы объектов.
Ответ 7
Есть способ, вы просто попробуете это:
typedef void *(*FuncPtr)();
void *f() { return f; }
int main() {
FuncPtr f1 = f();
FuncPtr f2 = f1();
FuncPtr f3 = f2();
return 0;
}
Ответ 8
#include <stdio.h>
#include <stdint.h>
#include <stdlib.h>
typedef void *(*fptr)(int *);
void *start (int *);
void *stop (int *);
void *start (int *a) {
printf("%s\n", __func__);
return stop(a);
}
void *stop (int *a) {
printf("%s\n", __func__);
return start(a);
}
int main (void) {
int a = 10;
fptr f = start;
f(&a);
return 0;
}
Ответ 9
Если вы использовали С++, вы можете создать тип объекта State
(предполагая использование примера конечного автомата), в котором вы объявляете operator()
, который возвращает тип объекта State
по ссылке или указателю. Затем вы можете определить каждое состояние как производный класс State
, который возвращает каждый соответствующий другой производный тип из его реализации operator()
.