Kolejna porcja wiedzy z języka C 🔔. Jeżeli czytałeś(-aś) którykolwiek z innych moich artykułów, to ten wątek mógł Ci się przewinąć choć jeden raz, jednak występował jedynie w roli "epizodycznej" 🎬. Teraz chcę to osadzić "w roli głównej" 😊 i opisać dokładnie ze szczegółami. Oto wyjaśnienie czym jest niejaka dereferencja wskaźnika w języku C, zwana także operatorem wyłuskania 🎉!
DEREFERENCJA WSKAŹNIKA W JĘZYKU C, CZYLI NA CZYM POLEGA "WYŁUSKANIE"
Na początek samo pojęcie. Dereferencja polega na dostaniu się do wartości danego obiektu przez aktualny adres, na który wskazuje wskaźnik. Operacja ta jest też nazywana "wyłuskaniem", co w przenośni nazywamy "wyjmowanie" czegoś z innego miejsca, co jak najbardziej odpowiada tej sytuacji 👌.
Jest to pomocne w momencie, gdy chcemy zmienić wartość o odpowiednim typie danych zachowując tę samą referencję, czyli odniesienie do wskazanego obiektu danych, który nie jest sam w sobie wskaźnikiem 🛑. Mowa o tzw. "prostych" typach danych, takich jak 👇:
- "int",
- "float",
- "double",
- "char",
- "bool",
- "struct".
Przydaje się to szczególnie przy funkcjach akceptujących wskaźnik do danej wartości, aby móc utrwalać modyfikacje typów prostych poprzez przekazywanie parametrów formalnych przez referencję, a także przy korzystaniu z notacji wskaźnikowej dla argumentów tablic.
ZASADA DZIAŁANIA
Jeżeli nie widziałeś(-aś) artykułu o wskaźnikach, to teraz jest dobry moment, żeby się tam wrócić, ponieważ tutaj posługuję się zapisami, które zostały wyjaśnione wcześniej ⚠️!
Aby móc wykonać dereferencję, potrzebujemy dowolnej zmiennej oraz wskaźnika. No to tworzymy 👇:
int number = 57;
int* pointerToNumber = &number;Przypominam, że aby przypisać adres zmiennej, dodajemy znak ampersandu przed nazwą i taką postać przypisujemy do zmiennej wskaźnikowej ℹ️!
Od tej pory, możemy uzyskać dostęp do wartości na 2 sposoby:
- odwołując się do zmiennej,
- odwołując się do wskaźnika poprzez operator dereferencji.
Pokażę różnicę na wywołaniu funkcji "printf".
Pierwszy sposób, to rzekłbym "klasyczny" - po prostu podajemy samą nazwę zmiennej i tyle 😁:
printf("%d\n", number);Drugi sposób to także umieszczenie nazwy zmiennej (tym razem wskaźnikowej), lecz z przedrostkiem w postaci znaku asterysku (czy też "gwiazdki"):
printf("%d\n", *pointerToNumber);To jest operator wyłuskania, czyli "dostawanie się" do wartości przez adres, na który wskazuje ✅.
Oczywiście masz prawo także modyfikować wartość i w obu przypadkach postępujemy podobnie (pokażę na przykładzie dodawania liczby ➕).
Pierwszy sposób:
number += 10;Drugi sposób:
*pointerToNumber += 10;Najpierw wartość zostaje "wyłuskana" ze wskaźnika, a następnie dodajemy do niej 10 i wszystko zadziała bez problemu 😊!
Z CYKLU "DOBRZE TO ZAPAMIĘTAJ"
Pragnę w tym momencie poruszyć bardzo ważną rzecz ⚠️!
Pamiętaj, że z chwilą przypisania wskaźnikowi adresu do podanej zmiennej, zaczyna zachodzić między nimi relacja. To oznacza, że modyfikując wartość w dowolny z dwóch sposobów, "nowa" wartość będzie obowiązywać w dwóch miejscach naraz, bo na tym polega referencja!!!
Właśnie dlatego, w konstrukcjach występujących w językach o wyższej abstrakcji np. Java, C#, Python itd., jak modyfikujesz składową obiektu w klasie i przypiszesz tę samą referencję do innej zmiennej, to tę samą zmianę ujrzysz i w jednym, i w drugim miejscu w kodzie (dopóki nie utworzysz nowego obiektu albo nie zmienisz referencji) 😲!
Także pamiętaj: gdy kiedykolwiek będziesz miał(a) potrzebę wykonać kopię wartości, to musisz dodać nowy osobny obiekt danych i podstawić wartość "wyłuskanego" wskaźnika 👇:
int copyOfNumber = *pointerToNumber;Wtedy dowolne modyfikacje, na przykład:
copyOfNumber += 20;już będą od siebie niezależne, gdyż architektonicznie, to będą dwa osobne byty w pamięci 🧠.
Ostatnia rzecz: przenigdy nie próbuj "wyciągać" wartości z niezainicjowanego wskaźnika!
int* pointerToNumber;Próba odwołania się do niewiadomej wartości (czy nie daj Boże jej modyfikowania 😱) , skutkuje niezdefiniowanym zachowaniem, co w języku C jest najgorszą rzeczą ⛔!
![]() |
Dereferencja wskaźnika w języku C umożliwia "wydobycie" wartości ze zmiennej wskaźnikowej na podstawie adresu, jaki został mu przypisany.
To wszystko w tym temacie 🙂. Dereferencja wskaźnika może brzmi groźnie, jednak z biegiem czasu i opanowywaniem nowych zagadnień przekonasz się, że nie jest najtrudniejszą rzeczą w tym języku - są dużo trudniejsze 😉.
