Hallo, en welkom terug. In deze lezing wil ik het hebben over puntrekenkunde.
Nu we de relatie tussen arrays en pointers
begrijpen, wordt dit concept gemakkelijker te begrijpen.
We zeggen rekenen, maar dat doen we niet echt
-- het betekent alleen maar dat je plus
of min kunt doen, of de aanwijzer zelf kunt verhogen of verlagen.
Dus de echte kracht van het gebruik van verwijzingen naar arrays komt in het spel wanneer
u de elementen van een array wilt doorlopen.
Je wilt van het eerste element naar het einde gaan, je wilt ze doorlopen.
Dit zijn de echte powerpointers. Omdat pointers point-adressen gebruiken,
is elk element in de array gewoon een ander adres.
Dus je kunt gewoon plus plus doen op pointers en je kunt naar het volgende adres gaan.
Dus hier kan de waardenaanwijzer worden gebruikt om toegang te krijgen tot het eerste
gehele getal van de waardenarray.
Het kan worden gebruikt om toegang te krijgen tot waarden sub-0.
Dus als u zich de waarden herinnert, is de aanwijzer een aanwijzer
die verwijst naar een integerarray.
En we hebben het toegewezen aan het eerste element in de array door alleen de aanwijzer aan de arraynaam toe te wijzen.
We kunnen ook het adres van operator sub-0 gebruiken als we dat willen.
Maar wanneer we de verwijzing naar de waardenaanwijzer
verwijderen omdat deze naar het eerste element in de
array verwijst, krijgt u het eerste gehele getal in de sub-0-array met waarde.
Als u naar waarde sub 3 wilt verwijzen
via de aanwijzervariabele, hoeft u alleen maar 3 toe te voegen aan de waardenaanwijzer en vervolgens
de indirecte-operator toe te passen om deze te derefereren.
Dus je zou gewoon zoiets kunnen doen. U kunt waarden pointer plus 3 zeggen en
vervolgens dereferentie met het sterretje.
En meestal zet je het sterretje buiten aanhalingstekens om het duidelijk te maken.
Maar wat dit doet, is dat het waardenwijzer zegt, wat
een adres is van het eerste element in de array, het voegt er 3 aan toe.
En dus gaat het voor elke bytes voor gehele getallen optellen, het gaat
de bytes vermenigvuldigen met de gehele getallen.
Maar dit gaat in wezen verwijzen naar de sub
3, het 4e element in de array.
Dus in de uitdrukking asterisk values pointer plus i die
kan worden gebruikt om toegang te krijgen tot elke waarde in een waardenarray.
Dus als je deze uitdrukking begrijpt, kun je alles toevoegen aan i en
het zal je naar een specifieke elementarray verwijzen.
Dus als u de waarde sub 10 tot 27 wilt
instellen, hoeft u alleen maar een aanwijzer te
gebruiken, zeg waarden aanwijzer plus 10 en vervolgens dereferentie en zeg gelijk aan 27.
Dus je ziet hier de verschillende syntaxis.
Nogmaals, het is notationeel gemak, maar het is ook efficiënter in termen van het programma zelf.
Dus pointers, omdat ze zo nauw verwant zijn aan arrays, kunt u
gemakkelijk toegang krijgen tot elementen door alleen maar decrementele pointers te verhogen of
waarden toe te voegen of waarden van een pointer af te trekken.
Heel, heel handig.
Als u de waardenaanwijzer wilt laten wijzen naar het tweede element van de
waardenmatrix, kunt u de adresoperator toepassen op waarde sub 1 en de resultaten toewijzen aan de waardenaanwijzer.
We hebben dit gezien. Dit is gewoon een andere manier om hetzelfde te doen
als ik eerder heb genoemd als je de adres-suboperator wilt gebruiken.
Je kunt dit altijd doen als
je wilt, maar het is veel handiger om aanwijzerberekeningen te doen.
Als de waardenaanwijzer naar de waarde sub-0 wijst, kunt
u de waarde van één instellen door simpelweg één toe te voegen aan
de waarde van de waardenaanwijzer. En dit is echt waar we uitkomen met puntberekeningen.
Het enige wat u hoeft te doen is zeggen dat waarden punt
of plus gelijk is aan één, en nu wijst de waardenaanwijzer naar het tweede element in de
array of de eerste index.
Zeer, zeer mooie notatie, zeer gemakkelijk te doen.
Dit is dus een perfect geldige uitdrukking in c en
kan worden gebruikt voor verwijzingen naar elk gegevenstype, of het nu een geheel
getal is of wat dan ook. En je zou waarschijnlijk moeten nadenken over hoe nuttig dit kan zijn in karakters.
Als je een tekenaanwijzer hebt, kun je nu toegang krijgen tot
elk element, elk teken in een tekenreeks door gewoon een plus-plus op een aanwijzer te doen.
De operatoren voor verhogen en verlagen plus plus en min minus
zijn bijzonder handig bij het omgaan met deze
aanwijzingen, omdat u meestal van het ene element naar het volgende wilt gaan, enzovoort.
Het is niet zo gebruikelijk om 22 of min 20 op te
tellen, omdat je meestal in volgorde gaat.
Dus het gebruik van de increment-operator in een aanwijzer heeft hetzelfde effect als het toevoegen van een aan de aanwijzer.
Het gebruik van de decrement-operator heeft hetzelfde effect als het aftrekken van één van de aanwijzer.
Dus als u de plus plus-waardenaanwijzer zegt,
wordt de waardenaanwijzer ingesteld die naar het volgende gehele getal in de waardenarray wijst.
Min minus moet waardenaanwijzer zijn Gaat de waardenaanwijzer
instellen die naar het vorige gehele getal in de waardenarray wijst.
Maar je wilt voorzichtig zijn als je de min minus doet,
omdat je zeker wilt weten dat je in ieder geval in de array zit en niet op 0 staat.
En hetzelfde geldt voor plus plus.
Als u zich aan het einde van de array bevindt, wilt u geen fouten buiten de grenzen hebben.
Zorg er dus voor dat de waardenaanwijzer als u
deze verlaagt, aanvankelijk niet naar het begin van de waardenarray wees.
Een ander voorbeeld hier
waar we eigenlijk alle elementen in de array gaan
optellen, je ziet dat we een array-somfunctie hebben
en de functie neemt een array
en er is ook een constant geheel getal als parameters.
Binnen de functie gaan we een geheel getal maken.
We gaan die integer-som initialiseren naar 0, en we gaan een integer-pointer maken, een
pointer naar van het type int.
We gaan ook een aanwijzer maken
die constant is.
Dus wat dat betekent is dat je het adres ervan niet kunt veranderen.
Het wordt altijd array plus n en het wordt array end genoemd.
We doen dit omdat het onze lus efficiënter maakt als we hem zo instellen dat
hij naar het einde van de array gaat en alleen naar de aanwijzer kijkt.
Dus array end wijst naar het adres van het einde van de array.
We kunnen array zeggen, wat is wat wordt doorgegeven en dan is n de
grootte, de
grootte van de array.
Nu gaat de for-lus de aanwijzer van de regelvariabele van de lus initialiseren, wat
een aanwijzer is naar de array. En het enige wat u hoeft
te doen is als u een aanwijzer wilt toewijzen aan het eerste element van een array, u hoeft alleen
maar te zeggen dat pointer gelijk is aan array.
En dan is onze lusuitgangsvoorwaarde als de aanwijzer kleiner is dan het array-einde.
Onthoud dat een pointer een adres is en dat het array-einde ook een adres is.
Dus we zeggen dat als het adres bij pointer kleiner is dan pointer n,
we de body van de lus willen uitvoeren.
Pointer is gewoon een geheel getal, het is een hexadecimaal adres.
Elke keer dat we verhogen, gaat het naar het volgende adres. We hebben het eindadres, dus we kunnen
zeggen ga door de lus totdat we het einde bereiken.
En dan verhogen we de aanwijzer zelf, die het adres
zal verhogen om naar het volgende element in de array te gaan, in wezen omdat
dat is waar we naar verwijzen.
Dan hebben we in het lichaam van onze lus, we zeggen som plus is gelijk aan aanwijzer.
We ontkoppelen de aanwijzer om de waarde te
krijgen, want onthoud dat we de waarde willen krijgen die we niet willen hebben, het
adres van de aanwijzer of het adres van de aanwijzer waarnaar wordt verwezen.
En dan helemaal aan het einde, geven we de som terug. Dus dit gaat alle
elementen in een array optellen.
U zult in het algemeen opmerken dat we ook een verklaring van de functie daar hebben
gedaan, in tegenstelling tot de bovenkant van het bestand. Ik plaats ze meestal graag bovenaan het bestand.
Maar in het algemeen creëren we een array van 10 elementen, 3 7 min 9 enzovoort.
We geven dan de array of een som door en we
specificeren de grootte als 10.
En wat je gaat opmerken is dat het de waarde retourneert die de som van de array is.
Dus het is heel, heel leuk om deze puntberekening te gebruiken om door een array te
itereren, we kunnen gewoon
plus naar het volgende adres en ook naar het eindadres kijken om eruit te springen.
Dit is efficiënter als de aanwijzer naar het eindadres kijkt, in tegenstelling
tot een teller die naar minder dan n kijkt.
En je merkt ook dat we ze als constanten hebben gemaakt omdat de constanten niet
veranderen en dat is efficiënter met de compiler.
De array hier is een constante aanwijzer, wat betekent dat het adres niet kan veranderen.
Je had in dit voorbeeld ook moeten
opmerken dat om een array door te geven aan een functie, je gewoon de naam van de array opgeeft.
Dus we weten hoe we de functie moeten verhogen. En om een aanwijzer naar een array te produceren, hoeft
u alleen de naam van de array op te geven.
Dat zagen we toen we het eerste element van de array aan een pointer toewijzen.
Dit houdt dus in dat de aanroep van hun array-somfunctie,
wat aan de functie werd doorgegeven, in feite een verwijzing was naar de array-waarden.
En dit vertelt je echt dat arrays en pointers heel, heel nauw verwant zijn, dat een
array niets meer is dan een aanwijzer.
En dit verklaart waarom je de elementen van een array vanuit een functie kunt wijzigen.
Omdat tot nu toe, wanneer u gegevens doorgeeft aan een functie, die gegevens niet
buiten die functie worden gewijzigd, tenzij het een aanwijzer is.
Want daarom moeten we het adres voor de scanf doorgeven.
De enige manier waarop elementen buiten een functie kunnen worden gewijzigd, is
door verwijzingen naar een functie door te geven.
En omdat de elementen binnen die functie worden gewijzigd, betekent
dit dat je een aanwijzer doorgeeft.
En dit bewijst alleen maar weer dat wanneer
je dat arrays en pointers erg, erg op elkaar lijken in die zin dat arrays inderdaad pointers zijn die
gewoon een andere syntaxis gebruiken.
We gaan het hebben over hoe we een referentie kunnen doorgeven of echt
een kopie van een referentie kunnen doorgeven,
waardoor je gegevens in een functie buiten die functie kunt wijzigen.
Als je je herinnert van een van onze
vorige uitdagingen, moesten we telkens wanneer we gegevens in een functie wilden
veranderen, een globale variabele gebruiken.
Omdat we het concept van passeren door
verwijzing niet begrepen en we het concept van wijzers niet begrepen.
Maar ik heb al eerder genoemd dat een van de voordelen van pointers
is dat je nu gegevens binnen een functie kunt wijzigen en dat deze ook buiten die functie worden weergegeven.
Maar dat is een andere lezing.
Maar dat concept op zichzelf, vanwege het vorige voorbeeld, laat zien hoe
arrays in wezen pointers zijn.
Dus je zou je kunnen afvragen waarom de formele parameter in de functie niet als een pointer wordt verklaard.
Nou, dat zou kunnen. We zouden zoiets als dit kunnen doen, int array sum, int star array.
We hoeven dat niet als een array te declareren.
Het is volkomen geldig omdat arrays en pointers hetzelfde zijn als int star array.
We zeiden dat ze heel nauw verwant zijn.
U kunt dus een arraytype declareren als een type array van
ints binnen de array-somfunctie of u kunt het declareren als een aanwijzer naar int.
En daarom zie je veel functies die arrays accepteren als parameters of
als argumenten waarbij de parameters eigenlijk pointers zijn.
Dus als je indexnummers gaat gebruiken om te verwijzen naar de elementen van een array die aan een
functie wordt doorgegeven, declareer dan de parameter als een array.
Nogmaals, notatie gemak, het is gewoon een andere manier van notatie,
ofwel met behulp van de haakjes en subscript of met behulp van een aanwijzer.
De array zelf is meestal gemakkelijker te lezen in
termen van onderhoud van het programma, het geeft correcter het gebruik van de array door de functie weer.
Maar de aanwijzer is gemakkelijker te gebruiken.
En als je een argument gebruikt als een pointer naar de array, declareer dan dat het van het type
pointer is in de formele parameter.
Dus hier is een voorbeeld met de aanwijzernotatie van de
functie waar het vorige voorbeeld een array-notatie gebruikte.
Hier zeggen we gewoon int start array en
wat je zult opvallen is dat de functie meteen een stuk kleiner
wordt, omdat we de aanwijzer naar de array niet hoeven toe te wijzen aan het
eerste element zoals we deden.
De lus wordt ook een stuk kleiner omdat we die opdracht
in de eerste instructie niet hoeven te doen.
We kunnen gewoon zeggen totdat de array kleiner is dan het array-einde en we
kunnen de array verhogen. Dus het is een beetje minder code,
het is nog steeds heel duidelijk wat er aan de hand is, hopelijk als je arrays en pointers begrijpt.
We geven int star-array door, en we
hoeven die array niet meer te initialiseren omdat we het in
de aanwijzer doorgeven, we initialiseren de aanwijzer niet meer.
En dan stellen we eigenlijk het adres van het einde van
de array in op een
constante aanwijzer, array-einde. We gebruiken dat om uit
de lus te springen, en we zeggen gewoon som plus is gelijk
aan sterarray, waarbij we de indirectie-operator gebruiken om de array opnieuw te derefereren en de som terug te geven.
En dan is de hoofdfunctie precies hetzelfde, behalve dat de declaratie nu een aanwijzer is in plaats van een array.
Dus hier zijn 2 voorbeelden met verschillende notatie maar met dezelfde
functionaliteit en daarom zie je veel pointers als parameters
binnen een functieparameter.
Dus om hier samen te vatten zijn enkele dingen die geldig zijn als je pointers
gebruikt en dingen die niet geldig zijn.
Dus als we hier enkele variabelen declareren, declareren we een array met de naam earn en
deze bevat 3 elementen en dan declareren we 2 pointers.
Wat die aanwijzingen betreft, kunnen we rekenen. We kunnen zeggen pointer één plus plus.
We kunnen zeggen dat punt of 2 gelijk is aan punt of één plus 2.
We kunnen zelfs zeggen dat pointer 2 gelijk is aan verdienen plus één.
Het is volkomen geldig om dat te doen omdat je pointers hebt en je de pointers aanpast
aan het adres, zodat je puntberekeningen kunt doen.
U kunt geen puntberekeningen uitvoeren op arrays. Je kunt dus niet zeggen verdien plus plus.
Je kunt geen pointer 2 0 zeggen. 2 plus 0. 1
omdat dat adressen zijn.
En je verwijst niet echt naar
iets in een array.
En je kunt verdientijdpunten of één niet vermenigvuldigen om een punt of 2 te krijgen.
Die zijn ongeldig.
Let dus op de juiste syntaxis voor aanwijzerberekeningen en
begrijp ook dat puntberekeningen alleen kunnen worden toegepast op aanwijzers, niet
op arrays.
Ook functies die arrays verwerken, gebruiken pointers als argumenten.
U hebt de keuze tussen array-notatie en pointer-notatie voor
het schrijven van array-verwerkingsfuncties.
Dus als je de willekeurige functie gaat verwerken, is het prima om een aanwijzer als parameter te gebruiken.
U kunt kiezen welke u wilt gebruiken.
Maar het gebruik van pointers is meestal minder code en efficiënter.
Het gebruik van array-notatie maakt het duidelijker dat de functie met arrays
werkt en array-notatie ziet er meer bekend uit voor programmeurs die
enige programmeerachtergrond hebben in bepaalde talen.
Dus als je voor en Fortran en Pascal enzovoort programmeert,
mag je de pijlnotatie gebruiken.
Andere programmeurs zijn misschien meer gewend aan het werken met aanwijzers en
vinden de aanwijzernotatie misschien natuurlijker, alleen logischer.
Het komt dichter bij machinetaal met behulp van de
puntberekening en de aanwijzernotatie bij sommige compilers leidt het tot efficiëntere code, nog een reden
om het te gebruiken.
Dus laten we eens kijken naar deze voorbeelden
in codeblokken.
Dus hier is ons voorbeeld van de dia's. We hebben onze functiedeclaratie op regel 3.
Het is een matrixsom.
En in dit voorbeeld gaan we array-notatie gebruiken.
Dus we gaan de haakjes gebruiken als we indexen gebruiken.
En we gaan het doorgeven in
de waardenreeks noemen en de grootte doorgeven.
Dus de array-somfunctie heeft een integer-array. Welnu, het eerste dat u moet
doen, is de aanwijzer maken die u wilt gebruiken voor
puntberekeningen op regel 14. En dan moet je het einde
van de array toewijzen aan de adresarray plus de grootte.
Dat is het einde van de array, die u nu kunt gebruiken om de lus te verlaten.
Maar we moeten de aanwijzer aan de array toewijzen.
We weten dat we arrays kunnen toewijzen aan pointers om naar
het eerste element te verwijzen door alleen de naam van de array te gebruiken.
We hoeven het adres van de medewerker niet te gebruiken.
Als we wilden, zouden we zoiets kunnen doen.
En dit is ook prima.
En dan plus plus de aanwijzer. We verhogen de aanwijzer omdat het enige
wat dat doet, is opgehoogd naar het volgende adres. Het wijst naar het volgende element in de array.
En dan op regel 18, ontkoppelen we de aanwijzer om de som te berekenen, de som is
gelijk aan, de som plus de waarde van de aanwijzer waar hij naar wijst.
Dus als we dit bouwen, hebben we één waarschuwing, namelijk dat main geen
int is, we willen dit veranderen omdat het goed is
om foutwaarden van de main te retourneren en gewoon
return 0 te zeggen.
Je zou kunnen terugkeren als er een hoofdfout
was, je retourneert een negatieve. Nu we dit uitvoeren, zult u zien dat het alleen de som van
de waarden in de array uitvoert, dat is 3 plus 7 plus min 9 enzovoort, niet eens zeker
wat dat is, maar het lijkt erop dat het 21 is.
Nu kunnen we deze arrayparameter eenvoudig wijzigen om een aanwijzer
te nemen door gewoon de asterisk voor de aanwijzer te declareren.
We noemen het op dezelfde manier. We passen het gewoon aan. We hoeven de aanwijzer niet
meer te declareren. We willen waarschijnlijk de naam
veranderen om het gemakkelijker te maken, maar we hoeven deze pointer niet meer te declareren.
We willen nog steeds het einde van de array krijgen en
we hoeven het ook niet meer toe te wijzen.
We kunnen daar gewoon een leeg ding hebben. En het is misschien handiger om hier een while-lus te hebben.
Maar als we geen opdracht hebben, kunnen we de puntkomma daar gewoon plaatsen.
En nu zitten we goed. We willen het nog steeds de-refereren en we willen het nog steeds retourneren.
Maar als we
dit bouwen, willen we er
zeker van zijn dat we de functiedeclaratie als een aanwijzer definiëren, aangezien we deze hebben gewijzigd.
En dit kan elke naam zijn, maar we zullen gewoon consistent zijn.
Nu we bouwen,
willen we ervoor zorgen dat we alle variabelen die
we hebben gewijzigd opnieuw gebruiken.
Dus nu we het met succes hebben gebouwd, voeren we het uit en
je ziet dat je hetzelfde resultaat krijgt, namelijk 21.
Dus begrijp dit verschil tussen het gebruik van pointers als formele parameters in
arrays,
je kunt ze door elkaar gebruiken. Het is gewoon een notatie gemak.
Maar je hebt meestal minder code als je een aanwijzer gebruikt.
En je kunt het meer manipuleren en je kunt krachtigere dingen doen, het
is meestal ook efficiënter op basis van de compiler. Dank u.