Tablice i wskaźniki

Wskaźniki

Jeśli T jest pewnym typem, to T* jest typem wskaźnikowym do T. Wartością typu T* jest pewne miejsce w pamięci (np. zmienna), w którym przechowywana jest wartość typu T.

Wskaźniki przypominają referencje, ale są tu istotnie różnice:

Tablice

Jeśli potrzebujemy przechowywać wiele wartości tego samego typu możemy użyć tablic. Tablicę o nazwie t zawierającą n elementów typu T deklarujemy przez

T t[n];
możliwe jest też zainicjowanie tablicy w następujący sposób:
int tab[5] = {7, 13, -22, 8, 0};
Do elementów tablicy odwołujemy się przez nazwa_tablicy[indeks], przy czym numeracja rozpoczyna się od zera. W powyższym przykładzie dostępne są elementy tab[0], tab[1], tab[2], tab[3] oraz tab[4].

Można tworzyć również tablice wielowymiarowe, np. int t[10][20]; jest deklaracją tablicy o wymiarach 10x20. Do elementów odwołujemy się wówczas np. tak: t[4][6] (a nie przez t[4,6]).

Uwaga: Rozmiar tablicy musi być wartością stałą (możliwą do obliczenia w czasie kompilacji).

Tablice a wskaźniki

Do elementów tablicy można się odwoływać za pomocą wskaźników - nazwa tablicy może być używana jako wskaźnik do pierwszego (tj. tego o indeksie 0) elementu tablicy. Inaczej mówiąc, w powyższym przykładzie tab[0] oraz *tab są synonimami. Podobnie dla pozostałych elementów tablicy - można się do nich odwoływać przez tab[i] lub równoważnie przez *(tab+i).

Przykład: Poniższy kod wypisuje dwukrotnie zawartość tablicy t na ekran. Najpierw odwołujemy się do tablicy używając indeksów, a za drugim razem korzystając ze wskaźnika.

int t[5];

for(int i=0; i<5; ++i)
   cout << t[i] << endl;

for(int* p=t; p<t+5; ++p)
   cout << *p << endl;

Uwagi:

Napisy w stylu C

Napisy (ciągi znaków) są przechowywane jako tablice znaków (tj. typ char[] lub char*), przy czym znak o wartości 0 (ale nie '0'!) oznacza koniec napisu, np. napis "Ala" w tablicy t o rozmiarze 5 pamiętany jest jako
t[0]t[1]t[2]t[3]t[4]
'A''l''a'0'q'
przy czym ostatni znak jest nieistotny, bo znajduje się po kończącym napis zerze.

Uwaga: Znaki zapamiętywane są w pamięci komputera jako liczby z przedziału 0..255; kody te są nazywane ASCII. Np. literze 'A' odpowiada wartość 65, 'B' to 66, itd. Wartość 0 nie koduje żadnego znaku, jest wykorzystywana do oznaczenia końca napisu.

Przykład: Poniższy program

int main() {
   char n[5];
   n[0]='K'; n[1]='o'; n[2]='t'; n[3]=0;
   cout << n << endl;
   n[0]='L';
   cout << n << endl;
   n[1]=0;
   cout << n << endl;
}
powoduje wypisanie kolejno napisów Kot, Lot oraz L.

Tablice dynamiczne

Można stworzyć tablicę, której rozmiar nie jest znany w momencie pisania programu przy pomocy operatora new. Wyrażenie
new T[n];
tworzy nową tablicę typu T o rozmiarze n oraz zwraca wskaźnik do pierwszego elementu tej tablicy. Wskaźnik ten należy zapamiętać na zmiennej wskaźnikowej, w przeciwnym wypadku dostęp do tablicy zostanie utracony. Przed zakończeniem programu należy tablicę usunąć przy pomocy operatora delete, np.
delete[] p;
usuwa tablicę wskazywaną przez wskaźnik p. Tablica może zostać usunięta w dowolnym miejscu w programie, niekoniecznie w funkcji w której została stworzona. Można też tworzyć dynamicznie tablice wielowymiarowe, np. kod
int** t=new int*[20];
for(int i=0; i<20; ++i)
   t[i]=new int[10];
tworzy dynamicznie tablicę o wymiarach 20x10.