DODATEK A PRZEWODNIK JĘZYKA C
Lista deklaratorów pojawia się po ciągu specyfikatorów typu i klasy pamięci. Każdy deklarator zawiera jeden główny identyfikator - ten, który występuje w pierwszej alternatywie produkcji bezpośredni-deklarator. Specyfikatory klasy pamięci odnoszą się bezpośrednio do tego identyfikatora, ale jego typ zależy od postaci deklaratora. Deklarator jest zwrotem rozumianym w ten sposób, że jeśli jego identyfikator wystąpi w wyrażeniu w takiej samej postaci, jak w deklaratorze, to będzie oznaczać obiekt
0 wskazanym typie.
Jeśli rozważać tylko te części specyfikatorów deklaracji (p. A8.2), które dotyczą typu,
1 konkretny deklarator, to deklarację można zapisać jako „T D”, gdzie T jest typem, a D jest deklaratorem. Typ przypisany do identyfikatora w różnych postaciach deklaratora będzie opisywany indukcyjnie przy użyciu tego zapisu.
W deklaracji T D, w której D jest niczym nie ozdobionym identyfikatorem, typem identyfikatora jest T.
W deklaracji T D, w której D ma postać
( D1 )
typ identyfikatora w D1 jest taki sam, jak typ D. Nawiasy nie zmieniają typu, ale mogą zmienić rozbiór gramatyczny skomplikowanych deklaratorów.
W deklaracji T D, w której D ma postać * lista-kwalifikatorów-typuopc D1
a typem identyfikatora w deklaracji T D1 jest „modyfikator-typu T”, typem identyfikatora w D jest „modyfikator-typu lista-kwalifikatorów-typu wskaźnik do T”. Kwalifikatory następujące po * odnoszą się tylko do wskaźnika, a nie do wskazywanego przezeń obiektu.
Rozważmy dla przykładu deklarację int *ap[ ];
Tutaj ap[] pełni rolę D1 (deklaracja „int ap[]” - patrz p. A8.6.2 - nadawałaby ap typ „tablica elementów typu int”), lista kwalifikatorów typu jest pusta, a modyfikatorem typu jest „tablica elementów typu”. Zatem nasza deklaracja nadaje ap typ „tablica elementów typu wskaźnik do typu int” (lub prościej „tablica wskaźników do typu int”).
Jako inny przykład rozważmy deklaracje
int i, *pi, *const cpi = &i; const int ci = 3, *pci;
Zadeklarowano tutaj obiekt całkowity i oraz wskaźnik do obiektów całkowitych pi. Wartości stałego wskaźnika cpi nie można zmienić - zawsze będzie wskazywał na to samo miejsce pamięci, chociaż wartość w tym miejscu może być zmieniana. Obiekt całkowity ci jest stały i nie można go zmienić (chociaż można go zainicjować, jak powyżej). Typem pci jest „wskaźnik do const int”; wskaźnik pci można zmieniać tak, by pokazywał w inne miejsce pamięci, ale wartości wskazywanego przezeń obiektu nie można zmienić za pomocą pci.
A8.6.2 Deklaratory tablic
W deklaracji T D, w której D ma postać D1 [wy rażenie-stałe npc\
a typem identyfikatora w deklaracji T D1 jest „modyfikator-typu T”, typem identyfikatora w D jest „modyfikator-typu tablica elementów typu T”. Jeśli występuje wyraienie-stałe, to musi być typu całkowitego i musi mieć wartość większą niż zero. Jeśli nie podano wyrażenia stałego, opisującego rozmiar tablicy, to tablica ma typ niekompletny.
Tablice można konstruować z typów arytmetycznych, ze wskaźników, struktur i unii lub z innych tablic (tworząc tablice wielowymiarowe). Typ obiektów, z których jest zbudowana tablica, musi być kompletny - nie może być tablicą lub strukturą o typie niekompletnym. Dla tablic wielowymiarowych oznacza to, że można opuścić tylko pierwszy wymiar. Typ obiektu o niekompletnym typie tablicowym jest uzupełniany za pomocą innej, kompletnej deklaracji tego obiektu (p. A 10.2) lub za pomocą inicjowania (p. A8.7). Na przykład wiersz
float faf 17], *afp[17J;
deklaruje tablicę o elementach typu float i tablicę wskaźników do obiektów typu float. Wiersz
static int x3d[3][5][7];
deklaruje statyczną trójwymiarową tablicę elementów całkowitych o rozmiarze 3x5x7. Dokładniej mówiąc, x3d jest tablicą o trzech elementach, z których każdy jest
287