Osobiście uważam, że zdjęcia ze strzałkami skierowanymi w tę stronę lub takie, które utrudniają zrozumienie wskazówek. Sprawia, że wydają się abstrakcyjnymi, tajemniczymi istotami. Oni nie są.
Jak wszystko inne w twoim komputerze, wskaźniki są liczbami . Nazwa „wskaźnik” to po prostu fantazyjny sposób powiedzenia „zmiennej zawierającej adres”.
Dlatego pozwolę sobie poruszyć różne kwestie, wyjaśniając, jak właściwie działa komputer.
Mamy int, ma nazwę ii wartość 5. To jest przechowywane w pamięci. Podobnie jak wszystko zapisane w pamięci, potrzebuje adresu, inaczej nie bylibyśmy w stanie go znaleźć. Powiedzmy, że ikończy się pod adresem 0x12345678, a jego kolega jz wartością 6 kończy się tuż po nim. Zakładając 32-bitowy procesor, w którym int wynosi 4 bajty, a wskaźniki 4 bajty, wówczas zmienne są przechowywane w pamięci fizycznej w następujący sposób:
Address Data Meaning
0x12345678 00 00 00 05 // The variable i
0x1234567C 00 00 00 06 // The variable j
Teraz chcemy wskazać na te zmienne. Tworzymy jeden wskaźnik do int int* ip1, i jeden int* ip2. Podobnie jak wszystko w komputerze, te zmienne wskaźnikowe są również przydzielane gdzieś w pamięci. Załóżmy, że kończą się one pod następnymi sąsiednimi adresami w pamięci, zaraz po j. ip1=&i;Ustawiliśmy wskaźniki tak, aby zawierały adresy wcześniej przydzielonych zmiennych: („skopiuj adres i do ip1”) i ip2=&j. To, co dzieje się między wierszami, to:
Address Data Meaning
0x12345680 12 34 56 78 // The variable ip1(equal to address of i)
0x12345684 12 34 56 7C // The variable ip2(equal to address of j)
Więc to, co otrzymaliśmy, to jeszcze jakieś 4-bajtowe fragmenty pamięci zawierające liczby. Nigdzie w zasięgu wzroku nie ma mistycznych ani magicznych strzał.
W rzeczywistości, patrząc na zrzut pamięci, nie możemy stwierdzić, czy adres 0x12345680 zawiera znak intlub int*. Różnica polega na tym, w jaki sposób nasz program korzysta z treści przechowywanych pod tym adresem. (Zadaniem naszego programu jest właściwie po prostu powiedzieć procesorowi, co ma zrobić z tymi liczbami.)
Następnie dodajemy kolejny poziom pośrednictwa za pomocą int** ipp = &ip1;. Znowu otrzymujemy po prostu kawałek pamięci:
Address Data Meaning
0x12345688 12 34 56 80 // The variable ipp
Wzór wydaje się znajomy. Kolejny fragment 4 bajtów zawierający liczbę.
Teraz, gdybyśmy mieli zrzut pamięci powyższej fikcyjnej małej pamięci RAM, moglibyśmy ręcznie sprawdzić, gdzie wskazują te wskaźniki. Sprawdzamy, co jest przechowywane pod adresem ippzmiennej i znajdujemy zawartość 0x12345680. Który jest oczywiście adresem, pod którym ip1jest przechowywany. Możemy udać się pod ten adres, sprawdzić tam zawartość i znaleźć adres i, a na koniec udać się pod ten adres i znaleźć numer 5.
Więc jeśli weźmiemy zawartość ipp, *ippotrzymamy adres zmiennej wskaźnikowej ip1. Pisząc *ipp=ip2, kopiujemy ip2 do ip1, jest to równoważne ip1=ip2. W obu przypadkach otrzymalibyśmy
Address Data Meaning
0x12345680 12 34 56 7C // The variable ip1
0x12345684 12 34 56 7C // The variable ip2
(Te przykłady zostały podane dla procesora typu big endian)
ippprzy definiowaniu, aby Twoje pytanie było kompletne ;-)