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.
CZYM JEST DEREFERENCJA W JĘZYKU C?
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.
Jeżeli nie widziałeś(-aś) artykułu o wskaźnikach, to teraz jest dobry moment, aby się tam wrócić, ponieważ tutaj posługuję się zapisami, które zostały wyjaśnione wcześniej ⚠️!
JAK WYKONAĆ DEREFERENCJĘ W JĘZYKU C?
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".
JAK UZYSKAĆ DOSTĘP DO WARTOŚCI ZMIENNEJ WSKAZYWANEJ PRZEZ WSKAŹNIK?
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 ➕).
JAK MODYFIKOWAĆ WARTOŚĆ ZMIENNEJ WSKAZYWANEJ PRZEZ WSKAŹNIK?
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 😊!
Pragnę w tym momencie poruszyć bardzo ważną rzecz ⚠️!
CO SIĘ DZIEJE PO PRZYPISANIU ADRESU DO WSKAŹNIKA W JĘZYKU C?
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 😉.
