Jason. Cała informatyka w jednym miejscu!

Ponownie poruszę zagadnienie na temat relacji pomiędzy tablicą, a wskaźnikiem w języku C i C++. Wątek ten jest albo wymagany, albo poboczny w zależności od tego, w jakim języku piszecie (albo chcecie pisać) na co dzień. Zakładając, że przeczytaliście wprowadzenie do wskaźników, mogę Was poprowadzić za rękę dalej i zaprezentować Wam jak wygląda notacja wskaźnikowa w języku C do identyfikowania odpowiedniego elementu w tablicy. Tutaj jedynie Was wprowadzę do tematu, a w kolejnej części zastaniecie zapisy dla tablicy dwuwymiarowej. Tam dopiero się dzieje! Na razie, przeanalizujemy tablicę jednowymiarową. Zapraszam!

NOTACJA WSKAŹNIKOWA W JĘZYKU C DLA ARGUMENTÓW TABLICY

Zdecydowana większość obecnie wykorzystywanych języków programowania obsługuje wszystkim znany zapis "dostawania się" do konkretnego argumentu tablicy za pomocą nawiasów kwadratowych ([]). Wprowadzając w środek nich indeks w postaci dodatniej liczby całkowitej (niektóre języki obsługują też ujemne indeksy) uzyskujemy dostęp do konkretnej wartości. C i C++ wspiera również trudniejszą notację zwaną czasami "notacja wskaźnikowa". Polega ona na "przesuwaniu" adresu wskazującego początek tablicy dodając do niej liczbę całkowitą oraz na wykonaniu dereferencji wskaźnika po tym przesuniętym adresie celem uzyskania lub modyfikacji wartości. Przydaje się on wówczas gdy "zapominamy" o zapisie tablicowym przerzucając się w całości na wskaźniki. Przypominam, że notacja wskaźnikowa w języku C nie posiada żadnego liczbowego indeksu, tak jak ma to miejsce przy bardziej znanym zapisie!

TŁUMACZENIE NA JĘZYK KOMPUTEROWY

Spróbujmy teraz te teoretyczne fakty przerzucić na "programistyczny" język. Za przykład podam taką oto tablicę "numbers" noszącą powiedzmy, cztery argumenty typu "liczba całkowita". Wiemy, że w większości znanych języków będzie to wyglądać tak:

int[4] numbers;

W C i C++, nawiasy kwadratowe mają miejsce po nazwie tablicy, a nie po typie danych. A teraz zobaczmy jak to wygląda jako notacja wskaźnikowa w języku C. Tablica w językach C i C++ to tak naprawdę wskaźnik, zatem sama nazwa tablicy spełnia następującą równość:

numbers = &numbers[0]

Znak "ampersandu" przedstawia adres obiektu. Jak nie wierzycie, podstawcie sobie oba zapisy pod "printf" ze specyfikatorem "%p". Do zmiennej wskaźnikowej możemy też dorzucić stałą liczbę całkowitą. Przypuśćmy, że wpisaliśmy "numbers + 1". Co to oznacza dla prawej strony równania?

numbers + 1 = &numbers[1]

Czyli "przesunęliśmy" adres startu naszej tablicy o jeden argument do przodu (+4 bajty typu "int", pod warunkiem że to system 32-bitowy) i w ten sposób uzyskaliśmy adres drugiego argumentu tablicy "numbers" pod indeksem 1 (przypominam, że w tablicy argumenty są liczone od zera!). Pamiętajcie, aby się nie rozpędzić i akurat w naszym przypadku nie dać plus 4 lub więcej. Wówczas "wychodzimy" poza tablicę i dopuszczamy się naruszenia ochrony pamięci. Notacja wskaźnikowa w języku C nie wyłapie przekroczenia zakresu tablicy!!! Możemy bez przeszkód "wyłuskać" wskaźnik i z adresu "wyciągnąć" wartość liczbową. Zatem zakładając, że pierwszy argument posiada wartość 32, prawdziwa jest poniższa równość:

*numbers = numbers[0] = 32

Sprawa się komplikuje gdy chcemy "wyłuskać" konkretny indeks tablicy. Możecie pomyśleć, że to działa identycznie jak powyżej, natomiast muszę Was rozczarować:

*numbers + 1 = numbers[0] + 1 = 32 + 1 = 33

Widzicie? Operator dereferencji ma pierwszeństwo przy wykonywaniu, więc komputer najpierw dostanie się do adresu, "wyjmie" liczbę, a dopiero wtedy doda do niej jedynkę. Gdy chcemy, aby stało się po Waszej myśli, musimy osadzić wyrażenie w nawias w taki oto sposób (załóżmy, że druga liczba to 55):

*(numbers + 1) = numbers[1] = 55

Notacja wskaźnikowa w języku C jest równie "czuła" na nawiasy jak matematyka. Jeśli chcemy sprawnie się tutaj poruszać, musimy odróżniać jeden zapis od drugiego. Nie muszę dodawać, że ten przykład również stanowi zagrożenie w przypadku przekroczenia rozmiaru tablicy.


Dzięki za uwagę i skupienie. Nie smućcie się jeśli macie problem ze zrozumieniem. Ja miałem tak samo, jednak dałem sobie czas, usiadłem do przykładu, przeanalizowałem go sobie i wszystko było zrozumiałe. Przekonajcie się jak wygląda notacja wskaźnikowa dla tablicy 2D, to są dopiero jaja :D!

PODOBNE ARTYKUŁY