Składnia c dla funkcji zwracających Wskaźniki funkcji

Zwróć uwagę na następujący typ:

typedef int (*f1)(float);
typedef f1 (*f2)(double);
typedef f2 (*f3)(int);

f2 jest funkcją zwracającą wskaźnik funkcji. To samo dotyczy f3, ale typ funkcji, wskaźnik do którego zwraca f3, to f2. Jak mogę zdefiniować f3 bez typedefs? Wiem, że typedefs są czystszym i łatwiejszym do zrozumienia sposobem definiowania f3. Jednak moim zamiarem jest tutaj lepsze zrozumienie składni C.

Author: glglgl, 2012-05-25

6 answers

Zacznij od deklaracji dla f1:

int (*f1)(float);

Chcesz, aby f2 był wskaźnikiem do funkcji zwracającej f1, więc zastąp f1 w powyższej deklaracji deklaracją dla f2:

int (*      f1     )(float);
            |
      +-----+-----+
      |           |
      v           v
int (*(*f2)(double))(float);

Deklaracja brzmi jak

        f2                   -- f2
       *f2                   -- is a pointer
      (*f2)(      )          -- to a function
      (*f2)(double)          --   taking a double parameter
     *(*f2)(double)          --   returning a pointer
    (*(*f2)(double))(     )  --   to a function
    (*(*f2)(double))(float)  --     taking a float parameter
int (*(*f2)(double))(float)  --     returning int

Powtarzasz proces dla f3:

int (*(*    f2    )(double))(float);
            |
        +---+----+
        |        |
        v        v
int (*(*(*f3)(int))(double))(float);

Który czyta się jako

          f3                           -- f3
         *f3                           -- is a pointer
        (*f3)(   )                     -- to a function
        (*f3)(int)                     --   taking an int parameter
       *(*f3)(int)                     --   returning a pointer
      (*(*f3)(int))(      )            --   to a function
      (*(*f3)(int))(double)            --     taking a double parameter
     *(*(*f3)(int))(double)            --     returning a pointer
    (*(*(*f3)(int))(double))(     )    --     to a function
    (*(*(*f3)(int))(double))(float)    --       taking a float parameter
int (*(*(*f3)(int))(double))(float);   --       returning int
 111
Author: John Bode,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-05-25 18:07:35

W C++ cud szablonów może to nieco ułatwić.

#include <type_traits>

std::add_pointer<
    std::add_pointer<
        std::add_pointer<
            int(float)
        >::type(double)
    >::type(int)
>::type wow;
 13
Author: Puppy,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-05-25 17:36:28

Tak samo jak w przypadku typedef, tylko umieszczasz swoją definicję funkcji zamiast jej nazwy.

Oto jak wygląda f2:

typedef int (*(*f2)(double))(float);

Możesz zrobić f3 jako ćwiczenie, skoro zakładam, że to praca domowa;)

 7
Author: Blindy,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-05-25 17:26:19

Można to zrobić, ale będzie to bardzo mylące. Typedef są po to, aby ułatwić pisanie i czytanie tego krótkiego kodu.

Funkcja f, która nie pobiera argumentów i zwraca wskaźnik funkcji int (*)(float) prawdopodobnie byłaby czymś w rodzaju (niesprawdzonym):

int (*f())(float);

Następnie dla reszty musisz dodawać nawias, aż będzie wyglądał jak lisp.

 5
Author: David Rodríguez - dribeas,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-05-25 17:32:50

Poznaj regułę prawo-lewo :

Reguła "prawo-lewo" jest całkowicie regularną regułą do rozszyfrowywania C deklaracje. Może być również przydatny w ich tworzeniu.

 4
Author: Maxim Egorushkin,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-08-16 09:05:52

Użycie std::function:

typedef std::function<int(float)> f1;
typedef std::function<f1(double)> f2;
typedef std::function<f2(int)>    f3;

Lub

typedef std::function<std::function<std::function<int(float)>(double)>(int)> f3;
 0
Author: Inverse,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-06-01 17:38:46