Zaczynam od wskazówek i jestem trochę zdezorientowany. Wiem &
oznacza adres zmiennej, który *
może być użyty przed zmienną wskaźnika, aby uzyskać wartość obiektu wskazywanego przez wskaźnik. Ale wszystko działa inaczej, gdy pracujesz z tablicami, łańcuchami lub gdy wywołujesz funkcje z kopią wskaźnika zmiennej. Trudno w tym wszystkim dostrzec logikę.
Kiedy powinienem używać &
i *
?
RTFM
jest niepomocny i, szczerze mówiąc, bardzo niegrzeczny. Jeśli nie masz czasu na odpowiedź, szanuj tych, którzy poświęcają czas na udzielenie odpowiedzi na te pytania. Chciałbym móc to zrobić „anonowi”, ale oczywiście on / ona nie ma czasu, aby wnieść jakiś znaczący wkład.Odpowiedzi:
Masz wskaźniki i wartości:
Wskaźnik zmienia się w wartość za pomocą
*
:Przekształcasz wartość we wskaźnik za pomocą
&
:Edycja: W przypadku tablic są one traktowane bardzo podobnie do wskaźników. Jeśli myślisz o nich jako o wskaźnikach, będziesz używał ich
*
do uzyskania wartości w nich zawartych, jak wyjaśniono powyżej, ale jest też inny, bardziej powszechny sposób używania[]
operatora:Aby uzyskać drugi element:
Tak więc
[]
operator indeksowania jest specjalną formą*
operatora i działa w następujący sposób:źródło
int aX[] = {3, 4}; int *bX = &aX;
int *bX = &aX;
nie działa, ponieważaX
już zwraca adresaX[0]
(tj.&aX[0]
), Więc&aX
otrzyma adres, który nie ma sensu. Czy to jest poprawne?int aX[] = {3,4};
,int **bX = &aX;
jest błędem.&aX
jest typu „wskaźnik do tablicy [2]int
”, a nie „wskaźnik do wskaźnika doint
”. W szczególności nazwa tablicy nie jest traktowana jako wskaźnik do jej pierwszego elementu dla jedności&
. Możesz zrobić:int (*bX)[2] = &aX;
W przypadku tablic i funkcji istnieje pewien wzorzec; na początku jest to trochę trudne.
Kiedy mamy do czynienia z tablicami, warto pamiętać, że: gdy wyrażenie tablicowe pojawia się w większości kontekstów, typ wyrażenia jest domyślnie konwertowany z „tablicy N-elementowej T” na „wskaźnik do T”, a jego wartość jest ustawiana wskazywać pierwszy element w tablicy. Wyjątki od tej reguły są, gdy ekspresja tablicy pojawia się jako operand albo
&
czysizeof
operatorzy, lub gdy jest to dosłowne ciąg używany jako inicjator w deklaracji.Zatem, gdy wywołasz funkcję z wyrażeniem tablicowym jako argumentem, funkcja otrzyma wskaźnik, a nie tablicę:
Dlatego nie używasz
&
operatora do argumentów odpowiadających „% s” wscanf()
:Z powodu niejawnej konwersji
scanf()
otrzymujechar *
wartość wskazującą na początekstr
tablicy. Dotyczy to każdej funkcji wywoływanej z wyrażeniem tablicowym jako argumentem (prawie dowolna zstr*
funkcji*scanf
i*printf
funkcji itp.).W praktyce prawdopodobnie nigdy nie wywołasz funkcji z wyrażeniem tablicowym za pomocą
&
operatora, jak w:Taki kod nie jest bardzo powszechny; musisz znać rozmiar tablicy w deklaracji funkcji, a funkcja działa tylko ze wskaźnikami do tablic o określonych rozmiarach (wskaźnik do 10-elementowej tablicy T jest innego typu niż wskaźnik do 11-elementowej tablicy z T).
Gdy wyrażenie tablicowe pojawia się jako operator dla
&
operatora, typem wynikowego wyrażenia jest „wskaźnik do tablicy N-elementowej T” lubT (*)[N]
, która różni się od tablicy wskaźników (T *[N]
) i wskaźnika do typu podstawowego (T *
).W przypadku funkcji i wskaźników należy pamiętać o następującej zasadzie: jeśli chcesz zmienić wartość argumentu i odzwierciedlić go w kodzie wywołującym, musisz przekazać wskaźnik do rzeczy, którą chcesz zmodyfikować. Znów tablice wrzucają trochę małpiego klucza do prac, ale najpierw zajmiemy się normalnymi przypadkami.
Pamiętaj, że C przekazuje wszystkie argumenty funkcji według wartości; parametr formalny otrzymuje kopię wartości parametru rzeczywistego, a wszelkie zmiany parametru formalnego nie są odzwierciedlane w parametrze faktycznym. Typowym przykładem jest funkcja zamiany:
Otrzymasz następujące dane wyjściowe:
Parametry formalne
x
iy
są odrębnymi obiektami oda
ib
, więc zmianyx
iy
nie są odzwierciedlone wa
ib
. Ponieważ chcemy zmodyfikować wartościa
ib
, musimy przekazać do nich wskaźniki do funkcji zamiany:Teraz twój wynik będzie
Zauważ, że w funkcji wymiany nie zmieniamy wartości
x
iy
, ale wartości whatx
iy
point to . Pisanie do*x
różni się od pisania dox
; nie aktualizujemy samej wartościx
, uzyskujemy lokalizacjęx
i aktualizujemy wartość w tej lokalizacji.Jest to równie prawdziwe, jeśli chcemy zmodyfikować wartość wskaźnika; jeśli napiszemy
następnie modyfikujemy wartość parametru wejściowego
stream
, a nie to, na costream
wskazuje , więc zmianastream
nie ma wpływu na wartośćin
; aby to zadziałało, musimy przekazać wskaźnik do wskaźnika:Znów tablice wrzucają do prac trochę klucza małpiego. Gdy przekazujesz wyrażenie tablicowe do funkcji, funkcja otrzymuje wskaźnik. Ze względu na to, jak zdefiniowane jest indeksowanie tablic, można użyć operatora indeksu dolnego na wskaźniku w taki sam sposób, jak można go użyć na tablicy:
Zauważ, że obiekty tablicowe nie mogą być przypisane; tzn. nie możesz zrobić czegoś takiego
więc chcesz zachować ostrożność, mając do czynienia ze wskaźnikami do tablic; coś jak
nie zadziała.
źródło
Mówiąc prościej
&
oznacza adres , zobaczysz, że w symbolach zastępczych funkcji modyfikujących zmienną parametru, jak w C, zmienne parametrów są przekazywane przez wartość, przy użyciu znaku handlowego i środków, aby przejść przez odniesienie.*
oznacza dereferencję zmiennej wskaźnikowej, co oznacza uzyskanie wartości tej zmiennej wskaźnikowej.Powyższy przykład ilustruje, jak wywołać funkcję
foo
za pomocą funkcji pass-by-reference, porównaj z tymOto ilustracja użycia dereferencji
Powyższe ilustruje, w jaki sposób uzyskaliśmy adres
y
i przypisaliśmy go do zmiennej wskaźnikap
. Następnie odchylamyp
się, przyczepiając*
przód, aby uzyskać wartośćp
, tj*p
.źródło
Tak, to może być dość skomplikowane, ponieważ
*
jest używane do wielu różnych celów w C / C ++.Jeśli
*
pojawia się przed już zadeklarowaną zmienną / funkcją, oznacza to, że:*
daje dostęp do wartości tej zmiennej (jeśli typ tej zmiennej jest wskaźnikiem lub przeciążył*
operatora).*
ma znaczenie operatora mnożenia, w takim przypadku po lewej stronie musi być inna zmienna*
Jeśli
*
pojawia się w deklaracji zmiennej lub funkcji, oznacza to, że zmienna jest wskaźnikiem:Jeśli
&
pojawia się w deklaracji zmiennej lub funkcji, oznacza to ogólnie, że zmienna jest odniesieniem do zmiennej tego typu.Jeśli
&
pojawia się przed już zadeklarowaną zmienną, zwraca adres tej zmiennejDodatkowo powinieneś wiedzieć, że przekazując tablicę do funkcji, zawsze będziesz musiał przekazać jej tablicę, z wyjątkiem sytuacji, gdy tablica jest czymś w rodzaju cstringu zakończonego 0 (tablica char).
źródło
Kiedy deklarujesz zmienną wskaźnika lub parametr funkcji, użyj *:
Uwaga: każda deklarowana zmienna potrzebuje własnej *.
Jeśli chcesz wziąć adres wartości, użyj &. Jeśli chcesz odczytać lub zapisać wartość we wskaźniku, użyj *.
Tablice są zwykle traktowane jak wskaźniki. Kiedy deklarujesz parametr tablicy w funkcji, możesz równie łatwo zadeklarować, że jest wskaźnikiem (to znaczy to samo). Gdy przekazujesz tablicę do funkcji, faktycznie przekazujesz wskaźnik do pierwszego elementu.
Wskaźniki funkcji są jedynymi rzeczami, które nie do końca przestrzegają zasad. Możesz pobrać adres funkcji bez użycia & i możesz wywołać wskaźnik funkcji bez użycia *.
źródło
Przeglądałem wszystkie trudne wyjaśnienia, więc zamiast tego zwróciłem się do wideo z University of New South Wales na ratunek. Oto proste wyjaśnienie: jeśli mamy komórkę, która ma adres
x
i wartość7
, pośrednim sposobem na podanie adresu wartości7
jest&7
a pośrednim sposobem na podanie wartości pod adresemx
jest*x
. Więc.(cell: x , value: 7) == (cell: &7 , value: *x)
Innym sposobem, aby na to spojrzeć:John
siedzi w7th seat
.*7th seat
Będzie wskazywaćJohn
i&John
daaddress
/ lokalizację7th seat
. To proste wyjaśnienie pomogło mi i mam nadzieję, że pomoże również innym. Oto link do doskonałego wideo: kliknij tutaj.Oto inny przykład:
Dodatek : Zawsze inicjuj wskaźnik przed użyciem, jeśli nie, wskaźnik wskaże na cokolwiek, co może spowodować awarię programu, ponieważ system operacyjny uniemożliwi dostęp do pamięci, o której nie wiesz, ale po prostu
p = &x;
, przypisujemy wskaźnik do określonej lokalizacji.źródło
Właściwie masz to w zanadrzu, nic więcej nie musisz wiedzieć :-)
Dodałbym tylko następujące bity:
&
bierze zmienną i podaje adres,*
pobiera adres i daje zmienną (lub treść).char **p
oznacza to, żep
jest wskaźnikiem do wskaźnika dochar
.Jeśli chodzi o rzeczy działające inaczej, to nie tak naprawdę:
\0
).źródło
Myślę, że jesteś trochę zdezorientowany. Powinieneś przeczytać dobry tutorial / książkę na temat wskaźników.
Ten samouczek jest bardzo dobry na początek (jasno wyjaśnia, co
&
i jakie*
są). I tak, nie zapomnij przeczytać książki Pointers in C autorstwa Kenneth Reek.Różnica między
&
i*
jest bardzo wyraźna.Przykład:
źródło
Ok, wygląda na to, że Twój post został edytowany ...
Widzisz, jak możesz użyć,
&
aby uzyskać adres początku struktury tablicy? Następującezrobi to samo.
źródło