Czy wiele wskaźników może odnosić się do tej samej zmiennej w C?

7

Jest to cecha języka C, która często dezorientuje nowicjuszy, ale gdy staje się jasna, wydaje się magiczna: możesz mieć wiele wskaźników wskazujących na ten sam adres pamięci.

Rozważ ten scenariusz. Deklarujesz zmienną całkowitą „i”. Następnie deklarujesz trzy wskaźniki p, q i r. Przypisujesz im wszystkim adres zmiennej „i”.

Spójrz na ostatnią linijkę. r nie musi wiedzieć bezpośrednio o i. Wskazuje po prostu miejsce, w którym wskazuje „p”. A „p” wskazuje na „i”. Dlatego r wskazuje również na i.

Operator przypisania kopiuje tutaj adres, a nie wartość. Kiedy robisz r = p, nie kopiujesz liczby całkowitej zawartej w i. Kopiujesz adres pamięci zapisany w p.

Po uruchomieniu tego kodu „i” ma zasadniczo cztery nazwy. Dostęp do niego można uzyskać za pomocą „i”. Można się do niego odwoływać za pomocą *p. Możesz się do niego odwoływać używając *q. Możesz też odwoływać się do niego za pomocą *r.

Nie ma żadnych technicznych ograniczeń co do liczby wskaźników, które można w ten sposób „akumulować”.

Dlaczego to jest ważne?

To nie jest tylko składnia akademicka. Zmienia sposób myślenia o przepływie danych.

W językach z silnymi odniesieniami do obiektu kopiowanie obiektu często tworzy nową instancję w pamięci. W C kopiowanie wskaźnika jest tanie. To tylko adres pamięci. Szybko. Mały.

Dzięki temu różne części kodu mogą manipulować tymi samymi danymi bez powielania. Zmień *p i *q natychmiast zobaczysz zmianę.

Tworzysz aliasy pamięci.

Ryzyko pseudonimów

W tym miejscu „fajna funkcja” staje się wadą.

Jeśli wszystkie „p”, „q” i „r” wskazują na „i”, dowolne z nich może zmienić „i”.

Teraz i jest równe 10. *q jest równe 10. *r jest równe 10.

Ale co, jeśli zapomnisz, że „r” następuje również po „i”? Możesz założyć, że „i” jest stabilne, ponieważ nie dotknąłeś go bezpośrednio. Dotknąłeś tylko *q.

To jest zasób udostępniony. Współdzielone zasoby to miejsce, w którym występują wyścigowe warunki i nieoczekiwane nadpisywanie danych.

Jak zapobiegać niezamierzonym skutkom ubocznym

Jeśli chcesz mieć pewność, że jeden wskaźnik nie nadpisze przypadkowo danych przeznaczonych dla innego, użyj const.

Teraz „r” może przeczytać „i”. Może ją wskazać. Ale nie może tego zmienić.

W ten sposób wyznaczasz granice w języku, który ufa, że możesz ręcznie zarządzać pamięcią.

Gdzie jest używany w programowaniu systemów

Ten wzór jest obecny w całym kodzie systemu.

Struktury jądra często mają wiele wskaźników do tego samego bloku sterującego. Sterowniki urządzeń mapują te same rejestry sprzętowe na różne nazwy logiczne.

Zrozumienie, że wskaźniki to po prostu etykiety adresów, pomoże w rozwiązaniu tych problemów. Gdy pamięć ulegnie uszkodzeniu, śledź wskaźniki. Kto jeszcze