[MUSIK SPELA] DOUG Lloyd: pekare, här är vi. Detta är förmodligen kommer att vara den svåraste ämne att vi talar om i CS50. Och om du har läst något om pekare innan du kan vara lite hotfull att gå in den här videon. Det är sant pekarna tillåter dig möjlighet till kanske skruva upp ganska dåligt när du är arbeta med variabler, och data, och orsakar programmet att krascha. Men de är faktiskt riktigt bra och de tillåter oss ett riktigt bra sätt att passera data fram och tillbaka mellan funktioner, att vi annars inte kan göra. Och så vad vi verkligen vill göra här är tåg att du har bra pekar disciplin, så att du kan använda pekare på ett effektivt sätt att göra dina program så mycket bättre. Som jag sa pekare ge oss ett annat sätt att överföra data mellan funktioner. Nu om du minns från en tidigare video, när Vi pratade om variabel omfattning, nämnde jag att all data som vi passerar mellan funktioner i C passeras av värde. Och jag kanske inte har använt den term, vad jag menade det var att vi passerar kopior av data. När vi passerar en variabel till en funktion, vi faktiskt inte passera variabeln till funktionen, eller hur? Vi passerar en kopia av att data till funktionen. Funktionen gör vad den kommer och den beräknar ett visst värde, och kanske vi använder det värdet när det ger den tillbaka. Det fanns ett undantag till denna regel att passera i värde, och vi ska återkomma till vad det är lite längre fram i den här videon. Om vi ​​använder pekare istället att använda variabler, eller i stället för att använda variablerna själva eller kopior av variablerna, Vi kan nu passera variabler runt mellan fungerar på ett annat sätt. Detta innebär att om vi gör en förändring i en funktion, ändringen faktiskt kommer att ta effekt i en annan funktion. Återigen, detta är något som Vi kunde inte göra tidigare, och om du någonsin har försökt att byta värdet av de två variabler i en funktion, du har märkt detta problem slags smygande upp, eller hur? Om vi ​​vill byta X och Y och vi skicka dem till en funktion som kallas swap, insidan av funktionen byta variabler gör bytesvärden. Man blir två, två blir en, men vi egentligen inte ändra något i den ursprungliga funktionen i den som ringer. Eftersom vi inte kan, vi är bara arbeta med kopior av dem. Med pekare men vi kan faktiskt passera X och Y till en funktion. Denna funktion kan göra något med dem. Och dessa variabler värden kan faktiskt förändras. Så det är ganska en förändring i vår förmåga att arbeta med data. Innan vi dyker in pekare, jag tycker det är värt tar några minuter till gå tillbaka till grunderna här. Och ta en titt på hur datorminnesarbeten eftersom dessa två ämnen kommer att faktiskt vara ganska varandra. Som ni säkert vet, på din dator du har en hårddisk eller kanske en solid state drive, någon form av fillagring plats. Det är oftast någonstans i trakten av 250 gigabyte till kanske ett par terabyte nu. Och det är där alla dina filer i slutändan lever, även när datorn är avstängd off, kan du slå på den igen och du hittar dina filer finns igen när du startar om datorn. Men hårddiskar, som en hårddisk, en hårddisk eller en SSD-enhet, en SSD, är bara lagringsutrymme. Vi kan faktiskt inte göra något med de data som finns i hårddisken, eller i en SSD-enhet. För att verkligen förändra uppgifter eller flytta runt, Vi måste flytta den till RAM, random access memory. Nu RAM, har du en hel del mindre i din dator. Du kan ha någonstans i trakten av 512 megabyte Om du har en äldre dator, till kanske två, fyra, åtta, 16, kanske till och med lite mer gigabyte RAM. Så det är mycket mindre, men det är där alla flyktiga data existerar. Det är där vi kan förändra saker. Men när vi vänder vår datorn, all data i RAM-minnet förstörs. Så det är därför vi måste ha hårddisk för mer permanent placering av den, så att den exists- det skulle vara riktigt illa om varje gång vi visade vår datorn, varje fil i vårt system utplånades. Så arbetar vi inne i RAM. Och varje gång vi pratar om minne, ganska mycket, i CS50, vi pratar om RAM, inte hårddisken. Så när vi flytta saker i minnet, den tar upp ett visst utrymme. Alla de datatyper som Vi har arbetat med ta upp olika mängder utrymme i RAM. Så varje gång du skapar ett heltal variabel, fyra byte minne avsätts i RAM-minnet så att du kan arbeta med det heltal. Du kan förklara heltal ändra det, tilldela den till ett värde 10 ökas med en, så vidare och så vidare. Allt som måste ske i RAM, och du får fyra byte att arbeta med för varje heltal som du skapar. Varje tecken du skapa får ett byte. Det är bara hur mycket utrymme är behövs för att lagra ett tecken. Varje flottör, en verklig nummer, får fyra byte om det inte är en dubbel precision flyttal nummer, vilket gör att du kan har mer exakta eller fler siffror efter decimalkommat utan att förlora precision, som tar upp åtta byte minne. Långa longs, riktigt stora heltal, även ta upp åtta byte minne. Hur många byte minne gör strängar ta upp? Nåväl låt oss sätta ett stift i den frågan för nu, men vi ska återkomma till det. Så tillbaka till denna idé om minnet som en stor matris av bytestora celler. Det är verkligen allt det är, det är bara en enorm mängd celler, precis som alla andra array som du är bekant med och se, utom varje element är en byte bred. Och precis som en array, varje element har en adress. Varje element i en matris har ett index, och vi kan använda detta index för att göra s.k. direktåtkomst på matrisen. Vi behöver inte börja på början av arrayen, iterera igenom varje enda element därav, att hitta vad vi letar efter. Vi kan bara säga, jag vill komma till 15 element eller 100-elementet. Och du kan bara passera i det numret och få det värde du letar efter. På samma sätt varje plats i minnet har en adress. Så ditt minne kanske se ut så här. Här är en mycket liten del av minne, är detta 20 byte minne. De första 20 byte eftersom min behandlar det på botten är 0, 1, 2, 3, och så på ända upp till 19. Och när jag deklarerar variabler och när jag börjar arbeta med dem, systemet kommer att ställa avsätta lite utrymme för mig i detta minne för att fungera med mina variabler. Så jag kan säga, röding c lika kapital H. Och vad kommer att hända? Väl systemet kommer att avsatts för mig ett byte. I det här fallet valde byte nummer fyra, byte vid adress fyra, och det kommer att lagra brev huvudstad H där för mig. Om jag sedan säga int hastighet gräns är lika med 65, det är kommer att avsätta fyra byte minne för mig. Och det kommer att behandla de fyra byte som en enda enhet eftersom det vi jobbar med är ett heltal här. Och det kommer att lagra 65 i det. Nu redan Jag är typ av berättar en bit av en lögn, rätt, eftersom vi vet att datorer fungerar i binär. De förstår inte nödvändigtvis vad en kapital H är eller vad en 65 är, de bara förstår binära, nollor och ettor. Och så faktiskt vad vi lagrar där är inte bokstaven H och antalet 65, utan snarare de binära representation därav, som ser lite ungefär så här. Och särskilt när det gäller ramen för heltalsvariabel det kommer inte att bara spotta i, det kommer inte att behandla det som en fyra byte bit nödvändigtvis, det är faktiskt går att behandla det som fyra en byte bitar, som kan se ut så här. Och även detta är inte helt sant heller, på grund av något som kallas en endian, som vi inte gå in på nu, men Om du är nyfiken, du kan läsa på lite och stora endian. Men för den skull detta argument, till förmån för den här videon, låt oss bara anta att är, i Faktum är hur antalet 65 skulle vara representerade i minne på varje system, även om det inte helt sant. Men låt oss faktiskt bara få bli av med alla binära helt, och bara tänka på som H och 65, är det mycket lättare att tänka på det som att som en människa. Okej, så det verkar också kanske en lite slumpmässigt att I've- mitt system gav mig inte byte 5, 6, 7, och 8 för att lagra heltal. Det finns en anledning till det också, som vi kommer inte att komma in just nu, men räcker det vill säga att vad dator gör här är förmodligen ett bra drag på sin sida. Att inte ge mig minne som är nödvändigtvis rygg mot rygg. Även om det kommer att göra det nu om jag vill få en annan sträng, kallas efternamn, och jag vill att sätta Lloyd där. Jag kommer att behöva passa en karaktär, varje bokstav i det är kommer att kräva en karaktär, ett byte av minnet. Så om jag kunde sätta Lloyd i min samling så här jag är ganska bra att gå, eller hur? Vad saknas? Kom ihåg att varje sträng vi arbetar med i C avslutas med omvänt snedstreck noll, och vi kan inte utesluta att här heller. Vi måste avsätta en byte minne för att hålla det så vi vet när vår sträng är avslutad. Så återigen detta arrangemang av hur saker och ting visas i minnes styrka vara lite slumpmässigt, men det är faktiskt hur de flesta system är utformade. Att rada upp dem på multiplar av fyra skäl igen att vi inte behöver komma in just nu. Men detta, så är det tillräckligt att säga att efter dessa tre rader kod, detta är vad minne kan se ut. Om jag behöver minnesplatser 4, 8 och 12 för att hålla mina uppgifter, Detta är vad mitt minne kan se ut. Och bara vara särskilt pedantisk här, när Vi pratar om minne adresser vi vanligtvis göra det med hexadecimala beteckningar. Så varför gör vi inte konvertera alla dessa från decimal till hexadecimal notation bara för att det är i allmänhet hur vi hänvisar till minnet. Så istället för att vara 0 till 19, vad vi har är noll x noll till noll x1 tre. De är 20 byte minne som vi har eller vi tittar på i den här bilden precis här. Så allt detta sagt, låt oss steg bort från minnet för en sekund och tillbaka till pekare. Här är den viktigaste sak att komma ihåg när vi börjar arbeta med pekare. En pekare är ingenting mer än en adress. Jag ska säga det igen eftersom Det är så viktigt, en pekare är ingenting mer än en adress. Pointers är adresser till platser i minnet där variabler bor. Att veta att det blir förhoppningsvis en lite lättare att arbeta med dem. En annan sak som jag gillar göra är att ha sortera av diagram visuellt representerar vad som är händer med olika rader kod. Och vi kommer att göra detta ett par gånger i pekare, och när vi talar om dynamisk minnesallokering samt. Eftersom jag tror att dessa diagram kan vara särskilt praktiskt. Så om jag säger till exempel int k i min kod, vad som händer? Tja vad som i grund och botten händer är Jag får minne som reserverats för mig, men jag inte ens gillar att tänker på det så jag gillar att tänka på det som en låda. Jag har en låda och det är färgade grön eftersom jag kan sätta heltal i gröna rutor. Om det var ett tecken jag kan ha en blå låda. Men jag säger alltid, om jag skapar en låda som rymmer heltal att rutan färgas grönt. Och jag tar en märkpenna och jag skriver k på sidan av den. Så jag har en låda som kallas k, i vilket jag kan sätta heltal. Så när jag säger int k, det är vad som händer i mitt huvud. Om jag säger k är lika med fem, vad gör jag? Tja, jag sätter fem i rutan till höger. Detta är ganska enkelt, om Jag säger int k, skapa en ruta som kallas k. Om jag säger k lika med 5, sätta fem i rutan. Förhoppningsvis det är inte för mycket av ett språng. Här är där det går en lite intressant ändå. Om jag säger int * pk, bra även om jag inte vet vad detta med nödvändighet innebär, Det är helt klart fått något att göra med ett heltal. Så jag kommer att färga rutan grön-ish, Jag vet att det har något att göra med ett heltal, men det är inte ett heltal själv, eftersom det är en int stjärna. Det finns något lite annorlunda om det. Så ett heltal är inblandad, men annars är det inte avviker alltför mycket från vad vi pratade om. Det är en låda, dess fått en etikett, Det bär en etikett pk, och det är kapabel innehav int stjärnor, oavsett de är. De har något att göra med heltal, tydligt. Här är den sista raden men. Om jag säger pk = & k, whoa, vad som just hände, eller hur? Så detta slumptal, till synes slumpmässig nummer, får kastas i rutan där. Allt som är, är pk blir adressen för k. Så jag fastnar där k bor i minnet, dess adress, adressen till dess byte. Allt jag gör är att jag säger detta värde är vad jag kommer att sätta in i min låda som kallas pk. Och eftersom dessa saker är pekare, och eftersom ser på en sträng som noll x åtta noll c sju fyra åtta två noll är förmodligen inte mycket meningsfullt. När vi i allmänhet visualisera pekare, vi faktiskt göra det så pekare. Pk ger oss den information vi måste hitta k i minnet. Så i princip pk har en pil i den. Och om vi går längden av den pil, föreställa det är något du kan gå på, om vi promenera utmed längden av pilen, vid den yttersta spetsen av den pil, vi kommer att finna den plats i minnet där k bor. Och det är verkligen viktigt eftersom när vi vet var k bor, vi kan börja arbeta med data insidan av den minnesplatsen. Även om vi får ett pyttelitet bit framför oss nu. Så vad är en pekare? En pekare är en datapost vars värdet är en minnesadress. Det var att noll x åtta noll grejer pågår, det var en minnesadress. Det var en plats i minnet. Och vilken typ av en pekare beskriver den typ data du hittar på den minnesadressen. Så det är int stjärnigt del rätt. Om jag följer det pilen, är det kommer att leda mig till en plats. Och den platsen, vad jag hittar det i mitt exempel, är en grön färgad ruta. Det är ett heltal, det är vad jag hittar du om jag går till den adressen. Datatyp en pekaren beskriver vad hittar du på den minnesadress. Så här är riktigt cool sak dock. Pointers tillåter oss att passera variabler mellan funktioner. Och faktiskt skicka variabler och inte passera kopior av dem. För om vi vet exakt var i minnet för att hitta en variabel, Vi behöver inte göra en kopia av Det kan vi bara gå till den platsen och arbeta med den variabeln. Så i huvudsak pekare sort av att göra en datormiljö mycket mer som den verkliga världen, rätt. Så här är en analogi. Låt oss säga att jag har en anteckningsbok, rätt, och det är full av anteckningar. Och jag skulle vilja att ni uppdatera den. Du är en funktion som uppdateringar anteckningar, rätt. På det sätt som vi har varit arbetar så långt, vad händer är att du kommer att ta min bärbara dator, du kommer att gå till kopieringsbutik, du kommer att göra en Xerox kopia av varje sida av den bärbara datorn. Du lämnar min bärbara dator tillbaka på mitt skrivbord när du är klar, du ska gå och stryka saker i mitt anteckningsbok som är inaktuella eller fel, och sedan kommer du att passera tillbaka till mig stapeln av Xerox sidor som är en kopia av min bärbara dator med de ändringar som du har gjort i den. Och på den punkten, är det upp till mig som anropsfunktionen, som den som ringer, besluta att ta dina anteckningar och integrera dem tillbaka i min bärbara dator. Så det finns en mängd åtgärder involverade här, rätt. Liksom skulle det inte vara bättre Om jag bara säga, hej, kan du uppdatera min bärbara dator för mig, lämna dig min bärbara dator, och du tar saker och bokstavligen stryka dem och uppdatera mina anteckningar i min anteckningsbok. Och sedan ge mig min bärbara dator tillbaka. Det är typ av vad pekare tillåter oss att göra, de gör denna miljö mycket mer som hur vi fungerar i verkligheten. Okej, så det är vad en pekare är, låt oss tala om hur pekare fungerar i C, och hur vi kan börja arbeta med dem. Så det finns en mycket enkel pekare i C kallas nollpekaren. Noll pekaren pekar på någonting. Det verkar sannolikt som det är faktiskt inte en mycket bra sak, men vi får se en Lite senare på det faktum att denna nollpekare existerar faktiskt riktigt kan komma till hands. Och när du skapar en pekare, och du inte ställa in dess värde immediately- ett exempel på inställning dess värde omedelbart kommer att vara ett par glider tillbaka där jag sa pk lika & k, pk får k adress, som Vi får se vad det betyder, vi får se hur man kan koda det shortly- om vi inte ställa in dess värde till något meningsfull omedelbart, Du bör alltid ställa in pekaren pekar på noll. Du bör ställa in den att peka på någonting. Det är mycket annorlunda än bara lämnar det värde som det är och sedan förklara en pekare och bara om man antar Det är noll eftersom det är sällan sant. Så du ska alltid ställa värdet på en pekare till null om du inte anger dess värde till något meningsfullt omedelbart. Du kan kontrollera om en pekare värde är null använda likhetsoperatorn (==), Precis som du jämför alla heltal värden eller tecken värden med (==) också. Det är en speciell sorts konstant värde som du kan använda för att testa. Så det var en mycket enkel pekare, nollpekaren. Ett annat sätt att skapa en pekare är att extrahera adressen till en variabel du redan har skapat, och du gör det genom att använda & operatör adress extraktion. Som vi redan har sett tidigare i första diagrammet exemplet jag visade. Så om x är en variabel som vi har redan skapat av typen heltal, då och X är en pekare till ett heltal. & x är- minns, och kommer att extrahera adress sak på höger sida. Och eftersom en pekare är bara en adress, än & x är en pekare till ett heltal vars värde är där minnet x liv. Det är x adress. Så & x är adressen för x. Låt oss ta detta ett steg vidare och ansluta till något Jag hänvisade till i en tidigare video. Om arr är en rad dubbel, då & arr hakparentes jag är en pekare till en dubbel. OK. arr hakparentes i, om arr är en rad dubbel, sedan arr hakparentes i är den i: te elementet i nämnda matris, och & arr hakparentes jag är där i minne den i: te elementet i arr existerar. Så vad är innebörden här? Ett matriser namn, innebörden av hela denna sak, är att en array heter faktiskt själv en pekare. Du har jobbat med pekare längs varje gång du har använt en array. Kom ihåg från exemplet Rörlig omfattning, i slutet av videon jag presentera ett exempel där vi har en funktion kallas set int och funktion kallad set array. Och din utmaning att bestämma med eller utan, eller vad värden som vi skrivs ut slutet av funktionen, vid slutet av huvudprogrammet. Om du minns från det exemplet eller om du har sett videon, du vet att när er-samtalet till set int gör effektivt ingenting. Men uppmaningen att ställa array gör. Och jag slags slätade över varför som var fallet vid den tidpunkten. Jag sa bara, ja det är en matris, är det speciell, du vet, det finns en anledning. Anledningen är att en arrays Namnet är egentligen bara en pekare, och det finns denna speciella klammer syntax som göra det mycket trevligare att arbeta med. Och de gör idén om en pekaren mycket mindre hotfull, och det är därför de är sortera av presenteras på detta sätt. Men egentligen arrayer är bara pekare. Och det är därför när vi gjort en ändring till arrayen, när vi passerade en array som en parameter till en funktion eller som ett argument till en funktion, innehållet i arrayen faktiskt ändras i både den uppringda och den som ringer. Som för alla andra typer av variabel vi såg var inte fallet. Så det är bara något att ha i tänka på när du arbetar med pekare, är att namnet på en matris faktiskt en pekare till det första elementet i den arrayen. OK så nu har vi alla dessa fakta, låt oss fortsätta, höger. Varför vi bryr oss om där något bor. Väl som jag sa, det är ganska bra att veta var något bor så att du kan åka dit och ändra det. Arbeta med det och faktiskt har det som du vill göra med den variabeln börjar gälla, och inte träda i kraft på någon kopia av den. Detta kallas Namnåtergång. Vi går till referens- och vi ändra värdet där. Så om vi har en pekare och det kallas pc, och det pekar på ett tecken, då kan vi säga * pc och * pc är namnet på vad vi hittar om vi går till den adress som st. Vad vi kommer att finna att det finns en karaktär och * pc är hur vi hänvisar till data på den plats. Så vi kunde säga något i stil * PC = D eller nåt sånt, och det betyder att allt var på minnesadress pc, oavsett karaktär var tidigare Det är nu D, om vi säger * pc = D. Så här går vi igen med några konstiga C grejer, rätt. Så vi har sett * tidigare som på något sätt en del av datatyp, och nu är det som används i ett något annorlunda sammanhang tillgång till uppgifterna på en plats. Jag vet att det är lite förvirrande och det är faktiskt en del av denna helhet liknande, varför pekare har denna mytologi omkring dem som så komplicerat, är typ av en syntax problem, ärligt. Men * används i båda sammanhangen, både som en del av typnamnet, och vi kommer att se en liten senare något annat också. Och just nu är det dereference operatör. Så det går till referens, Det ger tillgång till uppgifter vid läget för pekaren, och gör att du kan manipulera den efter behag. Nu är mycket lik besöker din granne, höger. Om du vet vad du granne bor, du är inte umgås med din granne. Du vet att du råkar vet var de bor, men det betyder inte att man genom på grund av att ha den kunskap du interagerar med dem. Om du vill interagera med dem, du måste gå till deras hus, du måste gå till där de bor. Och när du gör det, då kan du interagera med dem precis som du skulle vilja. Och på samma sätt med variabler, du måste gå till deras adress Om du vill interagera dem, du kan inte bara vet adressen. Och hur du går till den adress är att använda *, den dereference operatören. Vad tror du händer om vi försöker och dereference en pekare vars värde är noll? Minns att noll pekaren pekar på någonting. Så om du försöker och dereference ingenting eller gå till en adress ingenting, vad tror du händer? Tja, om du gissade segmente fel, skulle du vara rätt. Om du försöker och dereference en null-pekare, du drabbas av en segmente fel. Men vänta, gjorde jag inte berätta för dig, att Om du inte kommer att ställa in värdet på din pekaren till något meningsfullt, bör du ställa till null? Jag gjorde och faktiskt segmente fel är lite av en gott uppförande. Har du någonsin deklarerat en variabel och inte tilldelas dess värde omedelbart? Så du bara säga int x; du inte faktiskt tilldela den till något och sedan senare i din kod, du skriver ut värdet på x, har fortfarande inte tilldelat den till någonting. Ofta får du noll, men ibland kan få några slumptal, och har du ingen aning om varifrån den kom. På samma sätt kan saker hända med pekare. När du deklarerar en pekare int * pk t.ex. och du inte tilldela den till ett värde, du får fyra byte för minnet. Oavsett fyra byte minne systemet kan finna att ha några meningsfullt värde. Och det kan ha varit något som redan finns att behövs inte längre av en annan funktion, så att du bara har de data var där. Vad händer om du försökte göra dereference någon adress som du don't- fanns redan bytes och information där, det är nu i pekaren. Om du försöker avreferera att pekaren, du kanske jävlas med en del av minnet att du inte hade för avsikt bråka med det hela. Och i själva verket du kan göra något riktigt förödande, som bryta ett annat program, eller bryta en annan funktion, eller göra något skadligt att du hade inte för avsikt att göra alls. Och så det är därför det är faktiskt en bra idé att ställa in pekare till null om du inte ställa dem till något meningsfullt. Det är förmodligen bättre på slutet av dagen för ditt program att krascha då för att det ska göra Något som skruvar upp ett annat program eller en annan funktion. Detta beteende är förmodligen ännu mindre perfekt än bara kraschar. Och så det är därför det är faktiskt en god vana att komma in för att ställa in pekare till null om du inte ställer in dem till ett meningsfullt värde omedelbart, ett värde som du känner och att du kan säkert den dereference. Så låt oss komma tillbaka nu och ta en titt på den övergripande syntaxen av situationen. Om jag säger int * p ;, vad har jag just gjort? Vad jag har gjort är detta. Jag vet värdet av p är en adress eftersom alla pekare är bara adresser. Jag kan dereference p med hjälp av * operatören. I detta sammanhang här, åtmin top minns * är en del av den typ. Int * är datatypen. Men jag kan dereference p med hjälp av * operatör, och om jag gör det, om jag går till den adressen, Vad hittar jag på denna adress? Jag kommer att hitta ett heltal. Så int * p är i grund och botten säger, är en adress sid. Jag kan dereference p och om Jag gör det kommer jag att hitta ett heltal vid denna minnesplats. OK så jag sade att det var en annan irriterande sak med stjärnor och här är där det irriterande sak med stjärnor är. Har du någonsin försökt att förklara flera variabler av samma typ på samma kodrad? Så för en andra, låtsas att linjen, koden jag har faktiskt där i grönt är inte där och det säger bara int x, y, z ;. Vad det skulle göra är faktiskt skapa tre heltalsvariabler för dig, en kallade x, som kallas y, och en som heter z. Det är ett sätt att göra det utan behöva dela på tre linjer. Här är där stjärnorna får irriterande igen men eftersom * är faktiskt en del av både typ namn och delvis av variabelnamnet. Och så om jag säger int * px, py, pz, vad jag faktiskt får är en pekare till ett heltal kallas px och två heltal, py och pz. Och det är förmodligen inte vad vi vill, det är inte bra. Så om jag vill skapa flera pekare på samma rad, av samma typ, och stjärnor, vad jag faktiskt behöver göra är att säga int * pa, * pb, * pc. Nu har just sagt att och nu talar om detta, du förmodligen aldrig kommer att göra detta. Och det är förmodligen en bra sak ärligt, eftersom du kanske av misstag utelämna en stjärna, nåt sånt. Det är nog bäst att kanske förklara pekare på enskilda linjer, men det är bara en annan av dessa irriterande syntax saker med stjärnor som gör pekare så svårt att arbeta med. Eftersom det är just detta syntaktiskt mess du har att arbeta igenom. Med praktiken gör verkligen bli en andra natur. Jag fortfarande gör misstag med det fortfarande efter programmering i 10 år, så bli inte upprörd om något händer till dig, är det ganska vanligt ärligt. Det är verkligen slags en brist i syntaxen. OK så jag slags lovat att vi skulle återkomma begreppet hur stor är en sträng. Tja, om jag sa att en sträng, vi har verkligen slags ljugit för dig hela tiden. Det finns ingen datatyp som kallas sträng, och faktum är att jag nämnde detta i en av våra tidigaste videor på datatyper, strängen var en datatyp som skapades för dig i CS50.h. Du måste #include CS50.h för att kunna använda den. Tja sträng är egentligen bara ett alias för något kallas char *, en pekare till ett tecken. Väl pekare, återkallelse, är bara adresser. Så vad är storleken i byte i en sträng? Jo det är fyra eller åtta. Och anledningen till att jag säger fyra eller åtta är eftersom det faktiskt beror på systemet, Om du använder CS50 ide, är char * storleken på en röding * Är åtta, det är en 64-bitars system. Varje adress i minnet är 64 bitar långt. Om du använder CS50 apparaten eller använda 32-bitars maskin, och du har hört det uttrycket 32-bitars maskin, vad är en 32-bitars maskin? Jo det bara innebär att varje adress i minnet är 32 bitar lång. Och så 32 bitar är fyra byte. Så en char * är fyra eller åtta byte beroende på ditt system. Och faktiskt alla datatyper, och en pekare till alla uppgifter skriver, eftersom alla pekare är bara adresser, är fyra eller åtta byte. Så låt oss återkomma till detta diagram och låt oss sluta den här videon med lite övning här. Så här är diagrammet vi slutade med i början av videon. Så vad händer nu om jag säger * pk = 35? Så vad betyder det när jag säger, * pk = 35? Ta en andra. * pk. I sammanhanget här, * är dereference operatör. Så när dereference operatör används, vi gå till adressen pekade på genom pk, och vi ändrar vad vi hittar. Så * pk = 35 på ett effektivt sätt gör detta till bilden. Så det är i princip syntaktiskt identisk med att ha nämnda k = 35. En till. Om jag säger int m, jag skapar en ny variabel som kallas m. En ny ruta, är det en grön ruta, eftersom det kommer att hålla ett tal, och det är märkt m. Om jag säger m = 4, ställde jag en heltal i den rutan. Om säga pk = & m, hur detta diagram förändring? Pk = & m, gör du ihåg vad & Operatör gör eller kallas? Kom ihåg att & vissa variabelnamn är adressen till ett variabelnamn. Så vad vi säger är pk får adress m. Och så effektivt vad händer diagrammet är att pk inte längre poäng k, men pekar på m. Igen pekare är mycket knepigt att arbeta med och de tar en hel del praxis, men eftersom deras förmåga att låta dig för att skicka data mellan funktioner och faktiskt har de ändringarna träder i kraft, få huvudet runt är verkligen viktigt. Det är förmodligen den mest komplicerade ämne vi diskuterar i CS50, men det värde som du får från att använda pekare långt uppväger de komplikationer som kommer från att lära sig dem. Så jag önskar er det bästa av lycka lära sig om pekare. Jag är Doug Lloyd, är detta CS50.