Подтвердить что ты не робот

Возвращение функции

Можно ли объявить некоторый тип функции func_t, который возвращает этот тип, func_t?

Другими словами, возможно ли вернуть функцию?

// func_t is declared as some sort of function pointer
func_t foo(void *arg)
{
  return &foo;
}

Или мне пришлось бы использовать void * и typecasting?

4b9b3361

Ответ 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().