116
ROZDZIAŁ 17. WSKAŹNIKI
Wskaźniki można również od siebie odejmować, czego wynikiem jest odległość dwóch wskazywanych wartości. Odległość zwracana jest jako liczba obiektów danego typu. a nie liczba bajtów. Np.:
int a[] - <1, 2, 3, 5, 7>; int *ptr ■ &a[2];
int diff ■ ptr - a; /* diff ma wartość 2 (a nie 2*sizeof(int)) */
Wynikiem może być oczywiście liczba ujemna. Operacja jest przydatna do obliczania wielkości tablicy (długości łańcucha znaków) jeżeli mamy wskaźnik na jej pierwszy i ostatni element.
Operacje arytmetyczne na wskaźnikach mają pewne ograniczenia. Przede wszystkim nie można (tzn. standard tego nie definiuje) skonstruować wskaźnika wskazującego gdzieś poza zadeklarowaną tablicę, chyba, że jest to obiekt zaraz za ostatnim (one past last), np.:
int a[] - {1, 2, 3, 5, 7>; int *ptr;
ptr - a + 10; /* niezdefiniowane •/ ptr «a - 10; /* niezdefiniowane •/ ptr = a + 5; /* zdefiniowanie (element za ostatnim) */
•ptr ■ 10; /• to już nie! •/
Nie można'1 również odejmować od siebie wskaźników wskazujących na obiekty znajdujące się w różnych tablicach, np.:
int a[] = {1, 2, 3>, b[) - {5, 7>;
int *ptrl - a, *ptr2 - b;
int diff * a - b; /* niezdefiniowane •/
Trzeba wiedzieć, że tablice to też rodzaj zmiennej wskaźnikowej. Taki wskaźnik wskazuje na miejsce w pamięci, gdzie przechowywany jest jej pierwszy element . Następne elementy znajdują się bezpośrednio w następnych komórkach pamięci, w odstępie zgodnym z wielkością odpowiedniego typu zmiennej.
Na przykład tablica:
int tab[] - {100,200,300};
występuje w pamięci w sześciu komórkach 1 2:
+-------—f--------+---------4--------+-------+--------+
I wartościI |wartosc2l lwartosc3l I
+--------+--------+--------+--------+--------+--------+
To znaczy standard nie definiuje co się wtedy stanie, aczkolwiek na większości architektur odejmowanie dowolnych dwóch wskaźników ma zdefiniowane zachowanie. Pisząc przenośne programy nic można jednak na tym polegać, zwłaszcza, że odejmowanie wskaźników wskazujących na elementy różnych tablic zazwyczaj nie ma sensu.
^Ponownie przyjmując, że bajt ma 8 bitów, int dwa bajty i liczby zapisywane są w formacie little endian