5 WSKAŹNIKI I TABLICE
Ćwiczenie 5.1. Tak jak została napisana, funkcja getint traktuje znaki + i —» P° których nie następuje cyfra, jako poprawne reprezentacje zera. Zmień tę funkcję tak, by oddawała je z powrotem na wejście.
Ćwiczenie 5.2. Napisz funkcję getfloat - zmiennopozycyjny odpowiednik funkcji getint. Jakiego typu wartość powinna zwracać getfloat jako swoją wartość funkcyjną?
W języku C występuje ścisła zależność między wskaźnikami i tablicami, ścisła do tego stopnia, że wskaźniki i tablice powinny być rozpatrywane jednocześnie. Każdą operację, którą można przeprowadzić za pomocą indeksowania tablicy, można również wykonać za pomocą wskaźników. Wersja wskaźnikowa będzie na ogół szybsza, ale - zwłaszcza dla początkujących - trochę trudniejsza do zrozumienia.
Deklaracja
int a[10];
definiuje tablicę a o rozmiarze 10, a więc blok dziesięciu kolejnych obiektów nazwanych a[0], a[1],a[9].
a:
a[0] a (11 a 19]
Zapis a[i] oznacza i-ty element tablicy a. Niech pa będzie wskaźnikiem do obiektów całkowitych, zadeklarowanym jako
int *pa;
wówczas przypisanie pa = &a[0];
ustawi pa tak, aby wskazywał na zerowy element tablicy a; wskaźnik pa zawieri więc adres elementu a[0].
pa:
—pewe-r^e-d—by
Teraz przypisanie
x = ♦pa;
skopiuje zawartość a[0] do x.
Jeśli pa wskazuje na pewien element tablicy, to - z definicji - pa+1 wskazuje na element następny, pa+i odnosi się do i-tego elementu po pa, a pa-i do i-tego elementu przed pa. Jeżeli więc pa wskazuje na a[0], to
♦(pa+1)
odnosi się do zawartości a[1 J; pa+i jest adresem a[i], a *(pa+i) jest zawartością a[i].
Te spostrzeżenia są prawdziwe niezależnie od typu lub rozmiaru elementów tablicy a. Znaczenie operacji „dodawanie 1 do wskaźnika”, a szerzej - całej arytmetyki na wskaźnikach, jest oparte na tym, że pa+1 wskazuje następny obiekt, a pa+i odnosi się do obiektu oddalonego od pa o i takich obiektów.
Ścisła odpowiedniość między indeksowaniem i arytmetyką na wskaźnikach jest oczywista. Wartością zmiennej lub wyrażenia typu tablica jest z definicji adres zerowego elementu tej tablicy. Zatem po przypisaniu
pa = &a[0J;
pa oraz a mają identyczne wartości. Ponieważ nazwa tablicy reprezentuje położenie jej elementu początkowego, przypisanie pa=&a[0] można także napisać w postaci
pa = a;
Większą niespodzianką, przynajmniej na pierwszy rzut oka, będzie to, że odwołanie do a[i] można zapisać jako *(a+i). W języku C wyrażenie a[i] przy obliczaniu jest przekształcane bezpośrednio na *(a+i) - obie te formy są równoważne. Po zastosowaniu operatora adresu & do obu form widać, że &a[i] oraz a+i także są identyczne: a+i
•
jest adresem elementu oddalonego o i elementów od a. A z drugiej strony, jeśli pa jest wskaźnikiem, to w wyrażeniach może wystąpić z indeksem: pa[i] jest równoważne 1 *(pa+i). Podsumowując, wyrażenie w postaci „tablica i indeks” jest równoważne z wyrażeniem w postaci „wskaźnik i przesunięcie” (ang. offset).
137