Udostępnij za pośrednictwem


Interpretowanie deklaratorów bardziej złożonych

Można dołączyć dowolny deklarator w nawiasach, aby określić szczególną interpretacje "złożonego deklaratora." Złożony deklarator jest identyfikatorem zakwalifikowanym przez więcej niż jedną tablicę, wskaźnik lub funkcje modyfikatora.Różne kombinacje tablicy, wskaźnika i funkcji modyfikatora można zastosować do pojedynczego identyfikatora.Ogólnie typedef można wykorzystać do uproszczenia deklaracji.Zobacz Deklaracje typedef.

Przy interpretacji deklaracji złożonych, nawiasów kwadratowych i nawiasów (czyli modyfikatorów prawej strony identyfikatora) mają pierwszeństwo przed gwiazdkami (czyli modyfikatorami lewej strony identyfikatora).Nawiasy kwadratowe i nawiasy mają ten sam priorytet i są powiązane od lewej do prawej.Po pełnej interpretacji deklaratora, jako ostatni krok stosowany jest specyfikator typu.Za pomocą nawiasów okrągłych, można zastąpić domyślną kolejność powiązań i wymusić szczególną interpretację.Nigdy nie należy używać nawiasów, jednak wokół nazwy identyfikatora są użyte samodzielnie.Nawiasy te mogą być błędnie interpretowane, jako lista parametrów.

Prostym sposobem do interpretowania złożonych deklaratorów jest odczytanie ich "od wewnątrz," za pomocą następujących czterech kroków:

  1. Zacznij od identyfikatora i patrz bezpośrednio na prawą stronę nawiasów kwadratowych lub nawiasów okrągłych (jeśli istnieją).

  2. Interpretuj te nawiasy kwadratowe lub nawiasy okrągłe, a następnie spójrz w lewą stronę gwiazdki.

  3. Jeśli napotkasz nawias zamykający na dowolnym etapie, wróć i zastosuj reguły 1 i 2 do wszystkiego co znajduje się w nawiasach okrągłych.

  4. Zastosuj specyfikator typu.

    char *( *(*var)() )[10];
     ^   ^  ^ ^ ^   ^    ^
     7   6  4 2 1   3    5
    

W tym przykładzie, kroki są numerowane w kolejności i mogą być interpretowane w następujący sposób:

  1. Identyfikator var jest zadeklarowana jako

  2. wskaźnik do

  3. funkcja powrotu

  4. wskaźnik do

  5. Tablica 10 elementów, które są

  6. wskaźniki do

  7. wartość char

Przykłady

Poniższe przykłady pokazują pozostałe deklaracje złożone i pokazują, jaki wpływ mogą mieć nawiasy na znaczenie deklaracji.

int *var[5]; /* Array of pointers to int values */

Modyfikator tablicy ma wyższy priorytet, niż modyfikator wskaźnika, więc var został zadeklarowany jako tablica.Modyfikator wskaźnika stosuje się do typu elementów tablicy; w związku z tym, elementy tablicy są wskaźnikami do wartości int.

int (*var)[5]; /* Pointer to array of int values */

W deklaracji dla var, nawiasy nadają modyfikatorowi wskaźnika wyższy priorytet niż modyfikator tablicy, i var zostaje zadeklarowany jako wskaźnik do tablicy pięciu wartości int.

long *var( long, long ); /* Function returning pointer to long */

Modyfikatory funkcji również mają wyższy priorytet niż modyfikator wskaźnika, więc deklaracja dla var deklaruje var, jako funkcje zwracającą wskaźnik do wartości long.Funkcje jest zadeklarowana tak, aby przyjmowała dwie wartości long jako argumenty.

long (*var)( long, long ); /* Pointer to function returning long */

Ten przykład jest podobny do poprzedniego.Nawiasy nadają modyfikatorowi wskaźnika wyższy priorytet, niż modyfikator funkcji i var jest zadeklarowany jako wskaźnik do funkcji, która zwraca wartość long.Ponownie, funkcja przyjmuje dwa argumenty long.

struct both       /* Array of pointers to functions */
{                 /*   returning structures         */
    int a;
    char b;
} ( *var[5] )( struct both, struct both );

Elementy tablicy nie mogą być funkcją, ale deklaracja ta pokazuje, jak deklarować tablicę wskaźników do funkcji.W tym przykładzie, var został zadeklarowany jako tablica pięciu wskaźników do funkcji, które zwracają struktury z dwoma elementami członkowskimi.Argumenty funkcji są zadeklarowane jako dwie struktury z tym samym typem struktury both.Należy zauważyć, że nawiasy wokół *var[5] są wymagane.Bez nich, deklaracja jest niedozwoloną próbą zadeklarowania tablicy funkcji, jak pokazano poniżej:

/* ILLEGAL */
struct both *var[5]( struct both, struct both );

Poniższa instrukcja deklaruje tablice wskaźników.

unsigned int *(* const *name[5][10] ) ( void );

Tablica name ma 50 elementów, zorganizowanych w tablicy wielowymiarowej.Elementy są wskaźnikami do wskaźnika, który jest stały.Ten punkt wskaźnika stałego do funkcji, która nie ma parametrów i zwraca wskaźnik do typu unsigned.

W następnym przykładzie funkcja zwraca wskaźnik do tablicy trzech wartości double.

double ( *var( double (*)[3] ) )[3];

W tej deklaracji, funkcja zwraca wskaźnik do tablicy, ponieważ funkcje zwracające tablice są niedozwolone.W tym miejscu var został zadeklarowany jako funkcja zwracająca wskaźnik do tablicy trzech wartości double.Funkcja var przyjmuje jeden argument.Argument, tak samo jak zwracany wskaźnik, jest wskaźnikiem do tablicy trzech wartości double.Typ argumentu jest nadawany przez złożony deklarator-abstrakcyjny.Nawiasy wokół gwiazdki typie argumentu są wymagane; bez nich, typ argumentu byłby tablicą trzech wskaźników do wartości double.Omówienie i przykłady abstrakcyjnych deklaratorów, można zobaczyć tutaj Abstrakcyjne deklaratory.

union sign         /* Array of arrays of pointers */
{                  /* to pointers to unions       */
     int x;
     unsigned y;
} **var[5][5];

Jak wynika z powyższego przykładu, wskaźnik może wskazywać na inny wskaźnik i tablica może zawierać tablice jako elementy.W tym miejscu var jest tablicą pięciu elementów.Każdy element jest tablicą z pięcioma wskaźnikami do wskaźników związków z dwoma elementami członkowskimi.

union sign *(*var[5])[5]; /* Array of pointers to arrays
                             of pointers to unions        */

Ten przykład pokazuje, jak umieszczanie nawiasów, zmienia znaczenie deklaracji.W tym przykładzie, var jest tablicą pięciu wskaźników do pięciu elementach tablicy wskaźników do związków.Aby zobaczyć przykłady sposobów użycia typedef w celu uniknięcia deklaracji złożonych, zobacz Deklaracje typedef.

Zobacz też

Koncepcje

Deklaracje i typy