Złożone deklaracje

Jak interpretować złożone deklaracje typu:

int * (* (*fp1) (int) ) [10]; ---> declaration 1
int *( *( *[5])())(); --------> declaration 2

Czy jest jakaś zasada, której należy przestrzegać, aby zrozumieć powyższe deklaracje?

Author: Peter Mortensen, 2009-12-12

7 answers

Oto świetny artykuł o tym, jak czytać złożone deklaracje w C: http://www.codeproject.com/KB/cpp/complex_declarations.aspx

Bardzo mi pomogło!

Szczególnie-powinieneś przeczytać sekcję "the right rule". Tu cytat:

Int * (*(*fp1) (int) ) [10]; Można to interpretować w następujący sposób:

  1. zacznij od nazwy zmiennej-------------------------- fp1
  2. nic w prawo, ale) więc idź w lewo, aby znaleźć * -------------- jest wskaźnikiem
  3. Jump out of nawiases and encounter (int) --------- do a funkcja, która przyjmuje int jako argument
  4. idź w lewo, znajdź * ---------------------------------------- i zwraca wskaźnik
  5. wskakuj w nawias, idź w prawo i uderz [10] -------- do tablicy 10
  6. idź w lewo znajdź * ----------------------------------------- wskaźniki do
  7. Go left again, find int -------------------------------- ints.
 15
Author: matekm,
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
2009-12-12 10:42:15

Możesz użyć cdecl*:

cdecl> explain int *( *( *a[5])())();
 declare a as array 5 of pointer to function
 returning pointer to function returning pointer to int
cdecl> explain int * (* (*fp1) (int) ) [10];
 declare fp1 as pointer to function (int) returning
 pointer to array 10 of pointer to int

*Linked to strona internetowa, która korzysta z tego narzędzia wiersza poleceń w backendzie.

 16
Author: Alex B,
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
2009-12-12 10:54:26

Już dawno nauczyłem się następującej metody:

Rozpocznij od identyfikatora typu (lub nawiasu wewnętrznego) i przesuń po spirali, biorąc element w prawo pierwszy

W przypadku

 int * (* (*fp1) (int) ) [10];

Możesz powiedzieć:

  • fp1 jest a (nic po prawej więc przesuń w lewo)
  • wskaźnik do (przesunięcie poza nawias wewnętrzny
  • funkcja przyjmująca int jako agument (pierwszy po prawej)
  • i zwraca wskaźnik do (exit from nawias)
  • tablica 10 elementów typu
  • wskaźnik do (nic po prawej)
  • int

W wyniku:

Fp1 jest wskaźnikiem do funkcji pobierającej int i zwracającej wskaźnik do tablicy 10 wskaźników do int

Rysowanie rzeczywistej spirali (przynajmniej w twoim umyśle) bardzo pomaga.

 7
Author: Remo.D,
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
2009-12-12 10:52:38

Aby rozwiązać te skomplikowane deklaracje, należy pamiętać, że pierwszeństwo operatora wywołania funkcji () i operatora indeksu tablicy [] jest wyższe niż operatora dereferencji *. Oczywiście, nawias () może być użyty do nadpisania tych precedensów.

Teraz opracuj swoją deklarację od środka, czyli od nazwy identyfikatora.

Int * (*(*fp1) (int) ) [10]; --->deklaracja 1

W oparciu o wspomnianą regułę precedensów powyżej możesz łatwo to zrozumieć, rozkładając deklarację jako

Fp1 * (int) * [10] * int

I odczytać bezpośrednio od lewej do prawej po angielsku jako "fp1 jest wskaźnikiem do funkcji akceptującej int i zwracającej wskaźnik do tablicy [10] wskaźników do int". Zauważ, że deklaracja jest łamana w ten sposób tylko po to, aby pomóc zrozumieć ją ręcznie. Kompilator nie musi analizować tego w ten sposób.

Podobnie,

Int *( *( *[5])())(); -------->deklaracja 2

Jest uszkodzony jako

[5] * () * () * int

Tak więc deklaruje "tablicę [5] typu wskaźniki do function (), która zwraca wskaźnik do function (), która z kolei zwraca wskaźnik do int".

 4
Author: Tanay,
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
2009-12-12 12:23:34

Choć już na to odpowiedziałeś, ale możesz też przeczytać ten artykuł:

http://unixwiz.net/techtips/reading-cdecl.html

 3
Author: whacko__Cracko,
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
2009-12-12 13:10:14

Zacznij od lewego identyfikatora i pracuj nad wyjściem, pamiętając, że nie ma wyraźnego grupowania [] i () bind przed *, NP:

    *a[]                 -- is an array of pointer
  (*a)[]                 -- is a pointer to an array
    *f()                 -- is a function returning pointer
  (*f)()                 -- is a pointer to a function

Tak więc czytamy int *(*(*fp1)(int))[10] jako:

         fp1                     -- fp1
        *fp1                     -- is a pointer
       (*fp1)(int)               -- to a function
                                      taking an int parameter
      *(*fp1)(int)               -- returning a pointer
     (*(*fp1)(int))[10]          -- to a 10-element array
    *(*(*fp1)(int))[10]          -- of pointer 
int *(*(*fp1)(int))[10]          -- to int

Deklaracja int *(*(*[5])())() stanowi nieco wyzwanie, ponieważ nie ma identyfikatora; zwykle widzisz to w deklaracjach funkcji, gdzie parametr jest tego typu:

void foo(int *(*(*[5])())(), double);

To ta sama zasada co nienazwany parametr int w deklaracji fp1. Tablica daje nam wskazówkę, można również szukać lewej wewnętrznej grupy nawiasów.

                         -- unnamed
         [5]             -- is a 5-element array ([] binds before *)
        *[5]             -- of pointers
       (*[5])()          -- to functions
      *(*[5])()          -- returning pointers
     (*(*[5])())()       -- to functions
    *(*(*[5])())()       -- returning pointers
int *(*(*[5])())()       -- to int
 3
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
2009-12-12 14:07:48

Zgodnie z ruchem wskazówek zegara / spirali:

* http://c-faq.com/decl/spiral.anderson.html
 3
Author: Michael Burr,
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
2009-12-12 15:54:58