2012-05-25 14 views
31

Rozważmy następujące typedefs:C składnia funkcji powracających wskaźników funkcji

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

f2 to funkcja, która zwraca wskaźnik funkcji. To samo z f3, ale typ funkcji, której wskaźnik zwraca f3, to f2. Jak mogę zdefiniować f3 bez typedefs? Wiem, że typedefs są czystsze i łatwiej zrozumieć sposób definiowania f3. Jednak moim zamiarem jest lepsze zrozumienie składni C.

+2

C lub C++? Ponieważ C++ ma kilka łatwiejszych sposobów wyrażania takich rzeczy. – Puppy

+7

[cdecl jest twoim przyjacielem] (http://cdecl.ridiculousfish.com/?q=declare+f3+as+pointer+do+funkcji+%28int%29+returning++pointer+do+funkcji+%28double%29+ return + wskaźnik + do + function +% 28float% 29 + return + int) –

+0

cdecl.org tłumaczy tylko z c-składni na angielski. Nie jest to zbyt użyteczne, gdy idziesz w drugą stronę, ponieważ musisz sformułować swoją deklarację idealnie w oczekiwanej formie, a nie w ten sposób działa język angielski czy jakikolwiek inny język naturalny. –

Odpowiedz

105

Start z oświadczeniem o f1:

int (*f1)(float); 

Chcesz f2 jako wskaźnik do funkcji powracającego f1, więc zastąpił f1 w zgłoszeniu powyżej deklaracji dla f2:

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

Deklaracja jest oznaczana jako

 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 

powtórzyć proces f3:

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

który brzmi

  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 
+9

+1, ponieważ to naprawdę odpowiada na oryginalne pytanie, które dotyczyło poprawnej składni w C ... – Macmade

+9

Kiedy twój młot jest w kształcie litery C, wszystko wokół wygląda jak kciuk ... – Spook

+1

Ta odpowiedź powinna być wydrukowana masowo i rozprowadzana w szkoły komputerowe, to najprostszy i najlepszy sposób na zrozumienie składni deklaracji funkcji wskaźników, dziękuję John Bode! –

7

To samo, co w przypadku typedef, tylko w miejscu jego nazwy umieszczana jest definicja funkcji.

Oto jak f2 wyglądałby następująco:

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

Można zrobić f3 jako ćwiczenie, ponieważ jestem przy założeniu jest to praca domowa;)

+6

Downwizer musi mieć lepsze umiejętności parsowania. – Blindy

+0

Odpowiedź, którą podasz, jest łatwo dostępna za pomocą wyszukiwarki Google. Jednak składnia dla więcej niż jednego poziomu (funkcja zwracająca wskaźnik funkcji zwracającej funkcję) nie jest łatwa do znalezienia. Odniesienie do pracy domowej było nieuzasadnione. – keveman

+2

To jest dokładnie to samo, zamień 'f2' w mojej formie na' f3' typedef. Nie wiesz, co masz na myśli przez wyszukiwarkę Google, to podstawowa składnia języka C. – Blindy

12

W C++, cud szablonów może to odrobinę łatwiej.

#include <type_traits> 

std::add_pointer< 
    std::add_pointer< 
     std::add_pointer< 
      int(float) 
     >::type(double) 
    >::type(int) 
>::type wow; 
+3

+1 dla "wow" :-) –

+0

Pytanie dotyczyło składni C, nawet jeśli post został oznaczony C++, więc to nie jest istotne IMHO ... Ale miła odpowiedź przy okazji. :) – Macmade

+1

Jest to być może czystsze niż nie używanie jakichkolwiek pomocy (ani "typedef" ani "add_pointer"), ale podejście "typedef" jest nadal czystsze (IMHO). –

5

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

Funkcja f że nie wymaga żadnych argumentów i zwraca wskaźnik funkcji int (*)(float) będzie prawdopodobnie coś jak (niesprawdzone):

int (*f())(float); 

Potem przez resztę po prostu trzeba zachować dodając nawias aż wygląda Lisp.

+0

+1: Po prostu nie rób tego. Lispski wygląd odpowiedzi Johna Bode'a brzmiał "nuff". –

0

Zastosowanie 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; 
4

pozwala poznać the right-left rule:

Reguła „prawo-lewo” jest całkowicie regularny reguła do rozszyfrowania C deklaracji. Może być również przydatny w ich tworzeniu.

Powiązane problemy