Witam i witam ponownie. W tym wykładzie chcę omówić arytmetykę punktową.
Teraz, gdy rozumiemy związek między tablicami i wskaźnikami,
ta koncepcja będzie łatwiejsza do zrozumienia.
Mówimy arytmetyka, ale tak naprawdę tego nie robimy
- tak naprawdę oznacza to, że możesz
zrobić plus lub minus albo inkrementację lub dekrementację na samym wskaźniku.
Tak więc prawdziwa moc używania wskaźników do tablic ma znaczenie,
gdy chcesz sekwencjonować elementy tablicy.
Chcesz przejść od pierwszego elementu do końca, chcesz przez nie iterować.
To są prawdziwe wskaźniki mocy. Ponieważ wskaźniki wskazują na
adresy, każdy element tablicy jest po prostu innym adresem.
Możesz więc po prostu zrobić plus plus na wskaźnikach i przejść do następnego adresu.
Więc tutaj wskaźnik wartości może być użyty do uzyskania dostępu do pierwszej liczby
całkowitej z tablicy wartości.
Można go użyć do uzyskania dostępu do wartości poniżej 0.
Więc jeśli pamiętasz wartości, wskaźnik jest wskaźnikiem wskazującym
na tablicę liczb całkowitych.
I przypisaliśmy go do pierwszego elementu tablicy, po prostu przypisując wskaźnik do nazwy tablicy.
Moglibyśmy również użyć adresu operatora pod-0, gdybyśmy chcieli.
Ale kiedy wyłuskujemy wskaźnik wartości,
ponieważ wskazuje on na pierwszy element
tablicy, poda pierwszą liczbę całkowitą w tablicy value sub-0.
Jeśli chcesz odwołać się do wartości pod
3 za pomocą zmiennej wskaźnikowej, wszystko, co musisz zrobić, to dodać 3 do wskaźnika wartości,
a następnie zastosować operator pośredni, aby ją wyłuskać.
Możesz więc po prostu zrobić coś takiego. Możesz powiedzieć wartości wskaźnik plus 3, a następnie odwołać
się do niego za pomocą gwiazdki.
I zwykle umieszczasz gwiazdkę poza cudzysłowami, aby było jasne.
Ale to, co to robi, to mówi, że
wskaźnik wartości, który jest adresem pierwszego elementu w tablicy, dodaje do niego 3.
I tak naprawdę doda dla każdego bajtu liczb całkowitych,
pomnoży bajty przez liczby całkowite.
Ale w istocie będzie to wskazywać na
sub 3, czwarty element tablicy.
Tak więc w wyrażeniu gwiazdka wskaźnik wartości plus i, którego
można użyć w celu uzyskania dostępu do dowolnej wartości zawartej w tablicy wartości.
Więc jeśli rozumiesz to wyrażenie, możesz dodać cokolwiek do i, a
to wskaże ci konkretną tablicę elementów.
Więc jeśli chcesz ustawić wartość od 10 do 27, wszystko,
co musisz zrobić, to jeśli używasz wskaźnika, powiedz
wartości wskaźnik plus 10, a następnie wyłuskuj go i powiedz równa się 27.
Widzisz więc tutaj inną składnię.
Ponownie, jest to wygoda notacji, ale jest też bardziej wydajna z punktu widzenia samego programu.
Tak więc wskaźniki, ponieważ są tak blisko związane z tablicami,
można łatwo uzyskać dostęp do elementów, po prostu zwiększając zmniejszające się
wskaźniki lub dodając wartości lub odejmując wartości od wskaźnika.
Bardzo, bardzo przydatne.
Aby ustawić wskaźnik wartości tak, aby wskazywał na drugi element tablicy
wartości, można zastosować operator adresu do wartości poniżej 1 i przypisać wyniki do wskaźnika wartości.
Widzieliśmy to. Jest to po prostu inny sposób na zrobienie tego
samego, o czym wspomniałem wcześniej, jeśli chcesz użyć operatora podrzędnego adresu.
Zawsze możesz to zrobić,
jeśli chcesz, ale znacznie wygodniej jest wykonywać arytmetykę wskaźników.
Jeśli wskaźnik wartości wskazuje na wartość poniżej
0, można ustawić w punkcie wartości jeden, po prostu dodając
jeden do wskaźnika wartości. I właśnie do tego dochodzimy z arytmetyką punktową.
Wszystko, co musisz zrobić, to powiedzieć, że wartości wskazują
lub plus równa się jeden, a teraz wskaźnik wartości wskazuje drugi element w
tablicy lub pierwszy indeks.
Bardzo, bardzo ładna notacja, bardzo łatwa do wykonania.
Jest to więc całkowicie poprawne wyrażenie w c i może
być używane do wskazywania dowolnego typu danych, niezależnie od tego, czy jest
to liczba całkowita, czy cokolwiek. I prawdopodobnie powinieneś pomyśleć o tym, jak przydatne może to być w postaciach.
Jeśli masz wskaźnik znakowy, możesz teraz uzyskać dostęp do
każdego elementu, każdego znaku w ciągu, wykonując po prostu plus plus na wskaźniku.
Operatory zwiększania i zmniejszania plus plus i minus minus są
szczególnie przydatne, gdy mamy do czynienia z tymi
wskaźnikami, ponieważ zazwyczaj będziesz chciał przejść od jednego elementu do drugiego i tak dalej.
Dodanie 22 lub minus 20 nie jest tak powszechne,
ponieważ zwykle idziesz po kolei.
Tak więc użycie operatora inkrementacji we wskaźniku ma taki sam efekt, jak dodanie go do wskaźnika.
Użycie operatora dekrementacji daje taki sam efekt, jak odjęcie jednego ze wskaźnika.
Mówiąc więc, wskaźnik plus plus wartości
ustawi wskaźnik wartości wskazujący następną liczbę całkowitą w tablicy wartości.
Minus minus powinien być wartościami pointer Ustawi
wskaźnik wartości wskazujący na poprzednią liczbę całkowitą w tablicy wartości.
Ale chcesz być ostrożny, robiąc minus minus, ponieważ
chcesz się upewnić, że jesteś przynajmniej w tablicy i nie jesteś na 0.
To samo dotyczy plusa plusa.
Jeśli jesteś na końcu tablicy, nie chcesz mieć żadnych błędów poza zakresem.
Dlatego upewnij się, że wskaźnik wartości, jeśli
go zmniejszasz, nie wskazuje początkowo początku tablicy wartości.
Kolejny przykład, w
którym zamierzamy zsumować wszystkie elementy tablicy, widzisz,
że mamy funkcję sumy tablicowej, a
funkcja przyjmuje tablicę, a
także przyjmuje stałą liczbę całkowitą jako parametry.
Wewnątrz funkcji utworzymy liczbę całkowitą.
Zamierzamy zainicjować tę sumę całkowitą do 0 i utworzymy wskaźnik liczby
całkowitej, wskaźnik do typu int.
Stworzymy również wskaźnik, który
jest stały.
Oznacza to, że nie możesz zmienić jego adresu.
Zawsze będzie to array plus n i będzie się nazywać array end.
Robimy to, ponieważ sprawia, że nasza pętla jest bardziej wydajna, jeśli ustawimy ją
tak, aby przechodziła do końca tablicy i po prostu patrzyła na wskaźnik.
Zatem koniec tablicy wskazuje na adres końca tablicy.
Możemy powiedzieć tablica, czyli to, co zostało przekazane, a n to
rozmiar,
czyli rozmiar tablicy.
Teraz pętla for zainicjuje wskaźnik zmiennej sterującej pętli, który
jest wskaźnikiem do tablicy. Wszystko, co musisz
zrobić, to przypisać wskaźnik do pierwszego elementu tablicy, wystarczy powiedzieć,
że wskaźnik równa się tablicy.
A następnie naszym warunkiem wyjścia z pętli jest sytuacja, w której wskaźnik jest mniejszy niż koniec tablicy.
Pamiętaj, że wskaźnik to adres, a koniec tablicy to także adres.
Więc mówimy, że jeśli adres we wskaźniku jest mniejszy niż wskaźnik
n, to chcemy wykonać treść pętli.
Wskaźnik to po prostu liczba całkowita, to adres szesnastkowy.
Za każdym razem, gdy zwiększamy, przechodzi do następnego adresu. Mamy adres końcowy, więc możemy powiedzieć,
że przechodzimy przez pętlę, aż dotrzemy do końca.
A potem zwiększamy sam wskaźnik, który będzie
zwiększał adres, aby przejść do następnego elementu w tablicy, ponieważ
właśnie na to wskazujemy.
Następnie mamy wewnątrz ciała naszej pętli, mówimy suma plus równa się wskaźnik.
Wyłuskujemy wskaźnik, aby uzyskać wartość,
ponieważ pamiętaj, że chcemy uzyskać wartość, której nie chcemy uzyskać
adresu wskaźnika lub adresu wskaźnika, na który wskazuje.
A potem na sam koniec zwracamy sumę. Więc to zsumuje
wszystkie elementy w tablicy.
Zauważysz w głównym, że zrobiliśmy tam również deklarację funkcji
w przeciwieństwie do początku pliku. Zwykle lubię umieszczać je na początku pliku.
Ale generalnie tworzymy tablicę 10 elementów, 3 7 ujemnych 9 i tak dalej.
Następnie przekazujemy tablicę lub sumę i określamy
rozmiar jako 10.
Zauważysz, że zwraca wartość będącą sumą tablicy.
Więc bardzo, bardzo miło jest używać tej arytmetyki punktowej do iteracji po tablicy,
możemy po prostu
dodać do następnego adresu, a także spojrzeć na adres końcowy, aby wyskoczyć.
Jest to bardziej wydajne, gdy wskaźnik patrzy na adres końcowy, w
przeciwieństwie do licznika, który patrzy na mniej niż n.
Zauważysz również, że stworzyliśmy je jako stałe, ponieważ stałe się nie zmieniają i
jest to bardziej wydajne w przypadku kompilatora.
Tablica tutaj jest stałym wskaźnikiem, co oznacza, że adres nie może się zmienić.
W tym przykładzie powinieneś
również zauważyć, że aby przekazać tablicę do funkcji, wystarczy podać nazwę tablicy.
Więc wiemy, jak przekazać podnieść funkcję. Aby utworzyć wskaźnik do tablicy,
wystarczy podać nazwę tablicy.
Widzieliśmy to, kiedy przypisujemy pierwszy element tablicy do wskaźnika.
Oznacza to, że wywołanie ich funkcji sumy tablicowej,
co zostało przekazane do funkcji, było w rzeczywistości wskaźnikiem do wartości tablicy.
I to naprawdę mówi ci, że tablice i wskaźniki są bardzo, bardzo blisko powiązane,
że tablica to nic innego jak wskaźnik.
To wyjaśnia, dlaczego możesz zmieniać elementy tablicy z poziomu funkcji.
Ponieważ do tego momentu, kiedy przekazujesz dane do funkcji, dane te nie są
zmieniane poza tą funkcją, chyba że jest to wskaźnik.
Dlatego, że musimy podać adres pliku scanf.
Jedynym sposobem zmiany elementów poza funkcją jest
przekazywanie wskaźników do funkcji.
A ponieważ elementy są modyfikowane wewnątrz tej funkcji,
oznacza to, że przekazujesz wskaźnik.
I to jest po prostu kolejny dowód
na to, że kiedy zauważysz, że tablice i wskaźniki są bardzo, bardzo podobne, to tablice są rzeczywiście
wskaźnikami używającymi tylko innej składni.
Porozmawiamy o tym, jak możemy przekazać przez odniesienie lub
naprawdę przekazać kopię odniesienia, co
pozwoli ci zmienić dane w funkcji poza tą funkcją.
Jeśli pamiętacie z jednego z naszych
poprzednich wyzwań, ilekroć chcieliśmy zmienić dane w funkcji, musieliśmy
użyć zmiennej globalnej.
Ponieważ nie rozumieliśmy pojęcia przekazywania
przez odniesienie i nie rozumieliśmy pojęcia wskaźników.
Ale wspomniałem wcześniej, jedną z zalet wskaźników jest to,
że można teraz zmieniać dane wewnątrz funkcji i zostaną one odzwierciedlone poza tą funkcją.
Ale to kolejny wykład.
Ale ta koncepcja sama w sobie z powodu poprzedniego przykładu pokazuje,
że tablice są zasadniczo wskaźnikami.
Więc możesz się zastanawiać, dlaczego formalny parametr wewnątrz funkcji nie jest zadeklarowany jako wskaźnik.
Cóż, może być. Moglibyśmy po prostu zrobić coś takiego, int array sum, int star array.
Nie musimy deklarować tego jako tablicy.
Jest to całkowicie poprawne, ponieważ tablice i wskaźniki są tym samym, co możemy powiedzieć int star array.
Wspomnieliśmy, że są naprawdę blisko spokrewnieni.
Możesz więc zadeklarować typ tablicy jako typ tablicy int
w funkcji sumy tablicowej lub możesz zadeklarować go jako wskaźnik do int.
I dlatego widzisz wiele funkcji, które akceptują tablice jako parametry lub jako
argumenty, w których parametry są w rzeczywistości wskaźnikami.
Jeśli więc zamierzasz używać numerów indeksowych do odwoływania się do elementów tablicy, która jest
przekazywana do funkcji, zadeklaruj parametr jako tablicę.
Ponownie, wygoda notacji, to po prostu inny sposób
notacji, albo użycie nawiasów i indeksu dolnego, albo użycie wskaźnika.
Sama tablica jest zwykle łatwiejsza do
odczytania pod względem obsługi programu, bardziej poprawnie odzwierciedla użycie tablicy przez funkcję.
Ale wskaźnik jest łatwiejszy w użyciu.
A jeśli używasz argumentu jako wskaźnika do tablicy, zadeklaruj, że jest to wskaźnik
typu w parametrze formalnym.
Oto przykład z notacją wskaźnika funkcji, w
której poprzedni przykład używał notacji tablicowej.
Tutaj po prostu mówimy int
start array, a zauważysz, że funkcja natychmiast staje się
znacznie mniejsza, ponieważ nie musimy przypisywać wskaźnika do tablicy do pierwszego elementu,
tak jak to zrobiliśmy.
Pętla również staje się znacznie mniejsza, ponieważ nie musimy
wykonywać tego przypisania w pierwszej instrukcji.
Możemy po prostu powiedzieć, że tablica jest mniejsza niż koniec tablicy
i możemy inkrementować tablicę. Więc jest trochę mniej kodu,
nadal jest bardzo jasne, co się dzieje, miejmy nadzieję, jeśli rozumiesz tablice i wskaźniki.
Przekazujemy int star array i
nie musimy już inicjalizować tej tablicy, ponieważ przekazujemy
ją we wskaźniku, nie inicjalizujemy już wskaźnika.
A następnie ustawiamy adres końca tablicy na
stały wskaźnik, koniec
tablicy. Używamy tego, aby
wyskoczyć z pętli, i po prostu mówimy suma plus
równa się star array, używając operatora pośredniego, aby ponownie wyłuskać tablicę, zwracając sumę.
A potem główna funkcja jest dokładnie taka sama, z wyjątkiem tego, że deklaracja jest teraz wskaźnikiem, a nie tablicą.
Oto 2 przykłady używające innej notacji, ale zapewniające tę samą
funkcjonalność i dlatego widzisz wiele wskaźników jako parametry
wewnątrz parametru funkcji.
Podsumowując, oto kilka rzeczy, które są ważne, gdy używasz wskaźników
i rzeczy, które są nieprawidłowe.
Jeśli więc zadeklarujemy tutaj jakieś zmienne, deklarujemy tablicę o nazwie zarabiaj, która
zawiera 3 elementy, a następnie deklarujemy 2 wskaźniki.
Teraz na tych wskaźnikach możemy zrobić arytmetykę. Możemy powiedzieć, że wskaźnik jeden plus plus.
Możemy powiedzieć, że punkt lub 2 równa się punktowi lub jeden plus 2.
Możemy nawet powiedzieć, że wskaźnik 2 równa się zarobkowi plus jeden.
Jest to całkowicie słuszne, ponieważ masz wskaźniki i modyfikujesz wskaźniki według adresu,
dzięki czemu możesz wykonywać arytmetykę punktową.
Nie możesz wykonywać arytmetyki punktowej na tablicach. Nie możesz więc powiedzieć zarobić plus plus.
Nie możesz powiedzieć wskaźnika 2 0. 2 plus 0. 1,
ponieważ to są adresy.
I tak naprawdę nie wskazujesz
niczego wewnątrz tablicy.
I nie możesz pomnożyć zarabiania razy punkt lub jeden, aby uzyskać punkt lub 2.
Te są nieważne.
Dlatego zwróć uwagę na poprawną składnię arytmetyki wskaźników i
zrozum, że arytmetyka punktowa może być stosowana tylko do wskaźników, a nie
do tablic.
Również funkcje przetwarzające tablice w rzeczywistości używają wskaźników jako argumentów.
Masz wybór między notacją tablicową a notacją wskaźnika do
pisania funkcji przetwarzających tablice.
Więc jeśli zamierzasz przetwarzać funkcję losową, możesz użyć wskaźnika jako parametru.
Możesz wybrać, którego chcesz użyć.
Ale używanie wskaźników jest zwykle mniej kodowe i bardziej wydajne.
Używanie notacji tablicowej sprawia, że jest bardziej oczywiste, że funkcja działa z
tablicami, a notacja tablicowa wygląda bardziej znajomo dla programistów, którzy mają
pewne doświadczenie w programowaniu w niektórych językach.
Więc jeśli programujesz wcześniej, Fortran, Pascal i tak
dalej, możesz użyć notacji strzałek.
Inni programiści mogą być bardziej przyzwyczajeni do pracy ze wskaźnikami i mogą uznać notację wskaźnika
za bardziej naturalną, po prostu ma więcej sensu.
Jest bliżej języka maszynowego przy użyciu arytmetyki punktowej i
notacji wskaźnika w niektórych kompilatorach, co prowadzi do bardziej wydajnego kodu, co jest kolejnym
powodem, aby go używać.
Spójrzmy więc na te przykłady wewnątrz bloków
kodu.
Oto nasz przykład ze slajdów. Mamy deklarację funkcji w linii 3.
To jest suma tablicowa.
W tym przykładzie użyjemy notacji tablicowej.
Więc będziemy używać nawiasów, gdy używamy indeksów.
I nazwiemy to przekazaniem
tablicy wartości i przekazaniem rozmiaru.
Zatem funkcja sumy tablic przyjmuje tablicę liczb całkowitych. Cóż, pierwszą rzeczą, którą musisz zrobić,
jest utworzenie wskaźnika, którego chcesz użyć do arytmetyki punktowej
w linii 14. Następnie musisz przypisać koniec
tablicy do tablicy adresów plus rozmiar.
To koniec tablicy, której możesz teraz użyć do wyjścia z pętli.
Ale musimy przypisać wskaźnik do tablicy.
Wiemy, że możemy przypisać tablice do wskaźników,
aby wskazywały na pierwszy element, po prostu używając nazwy tablicy.
Nie musimy używać adresu agenta.
Moglibyśmy, gdybyśmy chcieli, moglibyśmy zrobić coś takiego.
I to też jest w porządku.
A potem dodajemy plus wskaźnik. Zwiększamy wskaźnik, ponieważ wszystko, co
robi, jest zwiększane do następnego adresu. Wskazuje na następny element w tablicy.
Następnie w linii 18. wyłuskujemy odniesienie do wskaźnika, aby obliczyć sumę, suma
równa się, suma plus wartość wskaźnika, na który on wskazuje.
Więc jeśli to zbudujemy, mamy jedno ostrzeżenie, które jest main nie
jest int, chcemy to zmienić, ponieważ dobrze jest
zwrócić wartości błędów z main i po prostu
powiedzieć return 0.
Możesz zwrócić, jeśli wystąpił błąd w
main, zwracasz ujemny. Teraz uruchomimy to, zobaczysz, że po prostu wykonuje sumę wartości w tablicy,
która wynosi 3 plus 7 plus minus 9 i tak dalej, nawet nie jestem pewien, co
to jest, ale wygląda na to, że jest to 21.
Teraz możemy łatwo zmodyfikować ten parametr tablicy,
aby pobierał wskaźnik, po prostu deklarując gwiazdkę przed wskaźnikiem.
Nazywamy to w ten sam sposób. Po prostu modyfikujemy. Nie musimy już
deklarować wskaźnika. Prawdopodobnie chcielibyśmy zmienić
nazwę, aby było to łatwiejsze, ale nie musimy już deklarować tego wskaźnika.
Nadal chcemy uzyskać koniec tablicy i nie
musimy już go już przypisywać.
Możemy tam mieć po prostu pustą rzecz. W rzeczywistości może być bardziej użyteczne posiadanie pętli while w tym miejscu.
Ale jeśli nie mamy przydziału, możemy po prostu wstawić tam średnik.
A teraz jest dobrze. Nadal chcemy usunąć odniesienie do niego i nadal chcemy go zwrócić.
Ale jeśli
to zbudujemy, chcemy
się upewnić, że zdefiniujemy deklarację funkcji jako wskaźnik, odkąd ją zmieniliśmy.
Może to być dowolne imię, ale będziemy po prostu konsekwentni.
Teraz budujemy,
chcemy się upewnić, że ponownie używamy wszystkich
zmienionych przez nas zmiennych.
Więc teraz zbudowaliśmy pomyślnie, uruchomiliśmy go i widzisz, że otrzymujesz
ten sam wynik, który wynosi 21.
Więc zrozum tę różnicę między używaniem wskaźników jako parametrów formalnych w
tablicach,
możesz ich używać zamiennie. To tylko notacyjna wygoda.
Ale gdy używasz wskaźnika, zazwyczaj masz mniej kodu.
Możesz nim bardziej manipulować i robić potężniejsze rzeczy, zwykle jest to
również bardziej wydajne w oparciu o kompilator. Dziękuję Ci.