[Powered by Google Translate] [Uge 4, Fortsat] [David J. Malan - Harvard University] [Dette er CS50. - CS50.TV] Det er CS50, og det er i slutningen af ​​uge 4. Så nogle gode nyheder og nogle dårlige nyheder. Ingen foredrag på mandag, ikke noget problem der i næste uge. [Studerende hepper] Du kommer ikke til at lide, hvor dette foregår. Men vi har dette i stedet næste onsdag, og der er også pr pensum 1 Fredag ​​forelæsning næste fredag, så vi kan blive på sporet. Men alt bliver filmet som sædvanlig, så ikke at bekymre dig. Og med hensyn til quiz 0 hvad vi vil gøre mod ugens udgang er Post på kursets hjemmeside cs50.net en forklaring af hvad slags forventninger du bør have, når det kommer til den første quiz. I almindelighed vil det være multiple choice, sand-falsk, korte svar, korte koder problemer. Du kommer ikke til at kunne forventes at gennemføre tilsvarende af et problem, som du ville se på en Pset, du som har en computer og en debugger og lignende, men der vil være små kodning problemer. Og ja, den bedste guide til at få en fornemmelse af, hvad CS50 quizzer er ligesom er at gå til cs50.net, gå til Quizzer link, og du kan se de sidste mange år værd af quizzer. Bare indse, at læseplanen ikke altid har været den samme gennem årene. Nogle gange kan vi tilføje, undertiden trække fra, så hvis du ser nogle emne på en af ​​de gamle quizzer at du ikke har nogen idé om, hvad det er vi taler om, så er det enten, at vi dækkede det eller at vi ikke dække det. Men i form af anmeldelser, denne søndag, mandag og tirsdag samt et kursus-dækkende gennemgang session søndag aften - tid og sted vil blive meddelt på kursets hjemmeside - du har alle en mulighed for at gennemgå med kursets pædagogiske stipendiater materialet til i år, både i snit og som en fuld klasse, og dem vil blive filmet som sædvanlig så godt. Ok. Så uden videre, en kommentar til bestået / ikke bestået og tilføje / slip. Du har måske set mine noter i aftes, og det er virkelig bare nogle ekstra forsikring at hvis du er blandt dem, især mindre komfortabel eller et sted midt imellem og du føler dig bare en lille smule i over dit hoved, indse, at er faktisk helt normal, og der er en rigelig støtte struktur på plads, hvoraf den ene kontortid var opsat på at forbedre desto mere pr min e-mail i går aftes, og indse også, at en mulighed som bestået / ikke bestået for en klasse som denne virkelig er ment som en mekanisme til at tage brodden af ​​et kursus som dette, så igen, hvis du bruger disse 10, 15, 20 timer prøver bare at få nogle Pset til at arbejde, og du ved, du er 90-95% af vejen men du kan ikke finde nogle skide bug, i bestået / ikke bestået model, der er slags okay. Ideen er, at med denne mekanisme, kan du derefter gå fokus på dine andre psets eller sove, eller hvad det er, du ønsker at fokusere på. Så indser, at du har indtil den kommende tirsdag - teknisk set den 5. mandag, men det er en ferie, så dette kommer tirsdag - at skifte fra bestået / ikke bestået til graduerede eller vice versa. Og hvis du virkelig på afgrunden og tænker på at droppe helt, behage fange mig efter foredrag eller drop mig en note. Vi ville elske at mindst chat, før du byde farvel. Ok. Så vi begyndte at tage støttehjulene off sidste gang. I særdeleshed har vi fokuseret på snor. String er noget, der er erklæret i CS50 biblioteket, specifikt i denne fil kaldet cs50.h, som vi vil begynde at se på denne og næste uge. Men snor er egentlig bare en forenkling af noget det er en lidt mere arcanely beskrevet som char *. Char vi er fortrolige med. Det er bare et enkelt tegn. Men * som mandag betegnede hvad? >> [Studerende] En pegepind. En markør. Og hvad er en pointer? >> [Studerende] En adresse. Det er ligesom en adresse, en placering i hukommelsen. Hvad er en adresse eller beliggenhed eller hukommelse? Igen, alle af os har bærbare computere med en koncert eller 2 GB RAM mest sandsynligt i disse dage, og det betyder, at du har en milliard eller 2 milliarder byte værd af hukommelsen. Og det er faktisk ligegyldigt, hvad det fysisk ser ud, men tage på tro, at du kan nummerere alle de individuelle bytes, at din egen bærbare computer har - dette er byte 0, dette er byte 1, dette er byte 2000000000 - og det er præcis, hvad en computer gør. Når du allokerer plads til et enkelt tegn, for eksempel, har det naturligvis til at leve et sted i computerens hukommelse, og måske er det ved byte nummer 12345, og det er et eller andet sted op her i computerens hukommelse. Og den adresse så af denne karakter er 12345. Nu, i uge 0 og nu hidtil har vi ikke virkelig plejet hvor i hukommelsen tingene gemmes, fordi vi normalt bruger symboler, variabler, og arrays til rent faktisk at få på vores data. Men som i mandags, og så meget desto mere i dag, er du nu vil have alle de mere ekspressive kapaciteter med at skrive programmer til virkelig at manipulere en computers hukommelse som du har lyst, for både gode formål og dårlige, bugs er en meget almindelig resultat på dette punkt i at lære det her. Men hvad betyder det egentlig at være en char *? Lad os gå videre tilbage til - og vi vil komme tilbage til Binky som lovet i dag. Lad os tage til et simpelt eksempel her. Lad mig gemme denne fil som compare.c, og lad mig bare få nogle skabelon kode her så omfatter stdio.h, lad mig også give mig selv omfatter cs50.h. Jeg zoome ind deroppe. Lad mig begynde at skrive main int, main (void), og nu vil jeg gøre noget som dette: printf ("Giv mig en streng:") og så vil jeg bruge string s bliver GetString at få en snor fra brugeren, så jeg har tænkt mig at bede brugeren om en anden. ("Giv mig en anden streng:") og jeg har tænkt mig at spørge dem via GetString at få det. Jeg vil kalde det t fordi t kommer efter s og s er en nice navn for en streng, hvis det er temmelig generisk. Så GetString, og nu vil jeg bare gøre en sanity check og jeg har tænkt mig at sige if (s == t) så jeg bare at fortælle brugeren printf ("Du har indtastet det samme \ n"); jeg ellers har tænkt mig at udskrive noget lignende ("Du har skrevet noget andet! \ n") eller hvad straffen vil være. Så sådan noget. Så som sædvanlig, vil jeg vende tilbage 0, som netop betød, at intet ondt er sket, og jeg har tænkt mig at gå videre og kompilere og køre dette program. Men mandag kørte vi dette program, og faktisk fik at vide, at HELLO ikke er goddag og farvel er ikke farvel. Den adfærd, vi så, var lidt mere som denne. Lad mig gå ind i min kilde bibliotek, zoome ind her, og lad os gør sammenligne. Compiled okay. Lad mig løbe sammenligne. Giv mig en streng: HELLO. Giv mig en anden streng: HELLO. Du skrev noget andet! Nå, lad mig prøve noget enklere ligesom 50, 50. Du skrev noget andet! hi, hi. Så klart er noget der foregår her. Men hvad var forklaringen på, hvorfor? Tilsyneladende, linie 12 er helt dysfunktionel. Hvad er det grundlæggende problem her? Yeah. >> [Studerende] Det er at sammenligne adresser. Ja, præcis. Det er faktisk sammenligne adresser hvor HELLO og HELLO gemmes. Det er ikke at sammenligne de breve HELLO igen og igen, fordi hvad der virkelig er sket, al den tid vi har brugt GetString - Denne tavle er igen vores computers hukommelse, og lad os sige, jeg kalder GetString efter at erklære en variabel s. Hvad betyder min hukommelse ud? Lad os vilkårligt sige, at s ser sådan ud. Det er et kvadrat. Og stort set enhver tid jeg har tegnet et stykke hukommelse på skærmen hvis det er 32 bit, jeg har tegnet kvadrater som dette, fordi faktisk i apparatet, en pegepind, en adresse, er 32 bit. Det er det samme som en int. Det kan variere baseret på edb-system. De af jer, der er vagt bekendt med det faktum, at din Mac eller pc er 64 bit, der rent faktisk angiver, at computeren bruger 64-bit pointers, 64-bit adresser, og blandt de upsides af det er dine computere kan have meget mere RAM end gårsdagens. Lang historie kort, tilbage i dag, hvor computerne kun brugt 32 bit at repræsentere adresser, det største antal bytes du kunne repræsentere i dette tilfælde var, hvad hvis du har 32 bit? Så 4 mia ret, fordi 2 til 32 er 4 mia. Dette nummer er blevet tilbagevendende i kurset. Så hvis du kun har 32 bits, det højeste antal, du kan tælle til er omkring 4 mia. Men det var en fundamental begrænsning af computere indtil for et par år siden fordi hvis du kun kan tælle så højt som 4 milliarder, det gør ikke noget, hvis du køber 8 GB RAM eller endda 5 gigabyte RAM; du kan ikke tælle, at høje, så det var nytteløst. Du kan kun få adgang de første 3 eller 4 gigabyte din computers hukommelse. Det er mindre af et problem nu, og du kan købe MacBook Pros og Dells med 8 GB RAM eller endnu mere i disse dage. Men hvis jeg afsætter ganske enkelt i dette program en pegepind, en pointer kaldet s, det kunne se sådan ud på skærmen, da vi faktisk er nødt til at skrælle tilbage dette lag. Jeg holde siger streng, men som mandag den streng er virkelig char *, adressen på nogle tegn. Så lad os tage denne uddannelse hjul fra, selv om vi vil fortsætte med at bruge GetString for nu. Så jeg har erklæret s, og det er en luns af hukommelse, 32 bit. Hvad er herinde i hukommelsen som standard? >> [Uhørlig student svar] Hvad er det? >> [Studerende] Garbage. >> Garbage. Præcis. Hvis du programmøren ikke sætte en værdi i en variabel, der ved, hvad det er? Nogle gange får du heldig, og det er 0, hvilket er lidt af en pæn, ren standardværdi, men som vi så mandag, nogle gange er det komplet nonsens, nogle virkelig store positive eller negative tal, der kom fra hvor? Yeah. >> [Studerende] Funktionen før. >> Yeah. Ofte den funktion, der blev kaldt før, fordi huske, som du kalder funktioner i hukommelsen, de fylder mere og mere plads nedefra, og så snart funktionen returnerer, bliver den pågældende hukommelse genbruges af den næste fyr, der bliver kaldt, er, hvem der bruger din samme skive af hukommelsen. Og hvis du har forladt skrald der, tidligere værdier, vi kan forveksles s som havende en vis værdi, når vi virkelig har ikke lagt noget der. Så vores RAM på dette punkt ser sådan ud. Nu på den højre side af linien 7 vi kalder GetString, som vi har gjort nu i flere uger, men hvad GetString virkelig gør? GetString skrevet af den CS50 personale er lidt intelligent i, at så snart brugeren begynder at skrive nøgler og hits Enter, GetString tal på, hvor mange tastetryk gjorde brugeren hit, hvor mange tegn skal jeg tildele RAM til. Og når denne RAM kommer fra, hvem ved? Det er et sted i computerens 2 gigabyte eller whatnot hukommelse. Men lad os antage, at computeren fandt plads til ordet HELLO lige her. Ordet jeg skrev var H-E-L-L-O. Og hvis vi trækker dette som en sekvens af tegn, kan vi trække det sådan her. Men jeg er nødt til at gøre 1 ekstra ting. Hvad hører i slutningen af ​​enhver streng i C? Den null karakter, som vi skriver som \ 0. Det er teknisk tallet 0, men det backslash gør hele klarere at dette er bogstaveligt talt tallet 0, det hele tal 0; det er ikke for eksempel quote-citat slut 0, som du måske skrive på tastaturet. Så dette er HELLO. Og hvad sagde vi siger mandag, at en funktion som GetString er faktisk tilbage alle disse uger? Det er ikke returnere en streng i sig selv, fordi der ikke rigtig har betydning fordi strenge ikke findes. De er en slags fabrikation i CS50 biblioteket. Hvad er virkelig en streng, mere teknisk? >> [Studerende] Det er det første tegn. Præcis. Det er ganske enkelt adressen på det første tegn, som brugeren skrevet i. Så hvis mit ord HELLO ender det op ved byte nummer 123 og derefter ved byte nummer 124, 125, 126, og så videre, hvis jeg bare nummer mine bytes fra 0 på op, hvad der virkelig GetString er på vej tilbage, er bogstaveligt talt antallet 123. Så hvad bliver sat i s er antallet 123, ikke bogstavet H, ikke ordet HELLO, ganske enkelt den adresse, hvor jeg kan finde det første bogstav i HELLO. Men det virker ikke som nok. Jeg bad dig om en streng, ikke et tegn. Så hvordan kan vi eller computeren vide, at Ello slags komme sammen med H? Hvad er den slags aftale, vi har? Yeah. [Studerende] Det holder fortæller selv at finde nogle flere tegn. >> Præcis. Der er denne human-computer konvention, hvorved når du har at gøre med strygere, ellers kendt nu som char stjerner, du simpelthen nødt til at finde ud af hvor enden af ​​hver snor i livet er ved virkelig bare iteration over det med en for-løkke, en while-løkke, uanset hvad, så når du finder den ende af snoren nu kan du udlede det, åh, hele ordet var HELLO. De af jer med forudgående erfaring med programmering måske kender i Java du kan bare ringe. længde og på andre sprog, kan du ringe til længde eller lignende. Det er fordi i en masse sprog, især ting kaldet objektorienterede sprog, længden af ​​noget er slags indkapslet inde i det stykke af selve dataene, ligesom vi indkapslede ID'er og navne og huse inde i en student på mandag. Men C er meget lavere niveau. Der er ingen genstande eller klasser, hvis du har hørt disse ord før. Alt hvad du behøver er virkelig hukommelse adresser. Så dette er en slags gammeldags måde at repræsentere interessante datastrukturer. Du har en startværdi som adressen på det første tegn og så lige nogle vilkårlige konvention, at alle er enige at følge. Så hvordan er streng længde gennemført, har vi foreslå? Strlen, strlen, som nogle af jer har nu brugt et par gange. Det er temmelig simpelt, ikke? Det er ligesom 2 linjer kode. Det er temmelig meget en for-løkke af en slags, måske med en ekstra lokal variabel. Men strlen bare nødt til at tage en pegepind og derefter begynde at lede efter \ 0. Og så snart den finder det, kan det vende tilbage det samlede antal skridt, det har taget i denne streng. Så vi kan udlede af dette, hvad der foregår næste. Antag så jeg erklærer t som jeg har gjort i linje 10. Dette er noget garbage værdi. Hvem ved i første omgang? Men på den højre side af linjen på 10 jeg ringer GetString igen. Hvem ved, hvor det ender? Lad os vilkårligt sige, at operativsystemet fandt plads til det helt herover. Jeg tilfældigvis tilfældigvis skrive H-E-L-L-O igen, og så vi kan drage den samme slags billede. Men det faktum, at jeg har gentegnes dette billede er bevidst fordi det er en anderledes HELLO end denne. Så her kan dette være placering 456, er 457, og så videre. Så hvad bliver sat hvor spørgsmålstegnet engang var? I dette tilfælde 456. Vi plukke disse numre vilkårligt fordi virkelig efter dag Vi vil ikke bekymre sig så meget om, hvad adressen på noget er. Alt vi interesserer os er, at vi kan finde ud af adressen på nogle stykke af data ligesom HELLO. Så virkelig hvad de fleste mennesker gør i datalogi når vi taler om hukommelse adresser og taler om pointers specifikt, snarere end gider finde ud af 123 - hvem bekymrer sig, når det her egentlig er, vi bare vide, at det er på nogle numeriske adresse - Vi forenkler verden og bare sige, at s peger på, at karakter og t peger på dette tegn. Og det faktum, at det er en pil er helt bevidst fordi bogstaveligt nu s peger på H og t peger i den anden H fordi der i slutningen af ​​dagen, er det ligegyldigt, hvad adressen er, men det betyder noget, at vi har evnen til at udtrykke denne adresse med nogle stykke kode. Vi har ikke rigtig manipuleret disse adresser bare endnu så vil vi se, hvor vi kan indskyde og sortere af gøre ting med pegepinde, men for nu i linje 12 bogstaveligt hvilke værdier vi sammenligner i henhold til denne historie på linje 12? Vi siger, er 123 lig lig med 456? Og det er bestemt ikke tilfældet. Og selv begrebsmæssigt, denne pointer er absolut ikke det samme som dette fordi du kaldte GetString to gange, og GetString forsøger ikke at være super dygtig, Det forsøger ikke at indse, åh, du har skrevet HELLO 5 minutter siden; lad mig give dig det samme pointer som jeg gav dig før, det bare tildeler en ny bid af hukommelse, hver gang du kalder det. Så hvordan kan vi løse dette problem? Hvis højere niveau jeg ønsker at sammenligne strengene Hej og HELLO - Jeg er ligeglad med viserne - hvordan kan jeg gå om at besvare spørgsmålet, har brugeren skrive det samme? Hvad er nødvendigt her? Yeah. [Studerende] Brug en funktion. >> Jeg kan bruge en funktion ud af kassen. Jeg kan anvende en funktion kaldet strcmp, s-t-r-c-m-p, bare den forkortede version af at sige streng sammenligne. Og hvis vi går ind i for eksempel sammenligne 2, som er blandt nutidens uddelingskopier, Jeg gør præcis det. Jeg holdt alt andet det samme fra linje 1 ned til 26 eller deromkring, og nu mærke denne del har ændret sig bare en lille smule. Lad os ignorere linie 28 for et øjeblik og kun fokusere på denne ene. Hvad sagde vi sige mandag, at str Sammenlign gør? Det håndterer processen med at tage 2 pegepinde, s og t i denne sag, slags praktisk talt at sætte fingeren på de 2 bogstaver, og hvad det skal gøre, er noget i retning af en while-løkke eller en for-løkke, og det siger er disse det samme? Hvis dette er tilfældet, flytter den fingrene eller pointers fremad. Er det de samme, disse den samme, disse den samme, disse samme, disse det samme? Og ooh, jeg er i slutningen af ​​strengen på både s og t. Jeg har ikke fundet nogen modsigelser. Ja, disse strenge er den samme. Og hvad betyder str sammenligne afkast, hvis 2 strenge er de samme, tilsyneladende? Zero. Så 0 er godt i dette tilfælde, fordi hvis det returnerer -1 eller +1, det betyder, at er bare sker for at komme før t alfabetisk eller efter t. Og hvorfor skulle det være nyttigt at have en funktion, der fortæller dig, hvilken streng kommer før eller efter i en ordbog? [Studerende] Søger. >> Søgning og sortering. Så du kan gøre ting som binær søgning eller boble sortere eller fusionere slags hvor du er nødt til at sammenligne ting. Så vidt vi har slags skære nogle hjørner og kun talte om sortering i forbindelse med tal, fordi det er rart og let at tale om, men du kan helt sikkert sammenligne strenge, æble og banan, fordi hvis æble er kendt for at komme før banan, på samme måde, kan du flytte strenge rundt i hukommelsen, ligesom Rob gjorde med fletningen sortere i videoen og vi gjorde her på scenen med udvælgelse slags, insertion sortere og boble slags. Så hvor kan vi ellers tage det? Lad os prøve det. Lad os slags glemme, at lektie for et øjeblik og prøv nu og kopiere 1.C at gøre følgende. I linie 21 Jeg siger print noget, så jeg får en snor fra brugeren, så jeg kan kontrollere dette. Vi har ikke rigtig fået ind i denne vane endnu, men lad os nu gøre det. Lad os faktisk skrælle dette lag. Dette er virkelig char *. Denne fyr er virkelig char *. Så hvad vil det sige at være kontrol, hvis s == NULL? Det viser sig, at når du kalder en funktion som GetString eller mere generelt bare bede en computer til at give dig noget hukommelse, noget kunne gå galt. Du kunne være vanvittigt og bede computeren for en terabyte hukommelse ved at bede om billioner af bytes af hukommelse bare ikke findes i computeren, men GetString og andre funktioner kræver en måde at råbe ad dig hvis du har bedt om for meget. Og den måde GetString gør dette er, hvis du har bedt om mere hukommelse end der er tilgængelig på computeren, selvom det er super, super lav sandsynlighed fordi ingen af ​​os kommer til at skrive en billion tegn og derefter trykke på Enter, men lav sandsynlighed selvom det kan være, jeg stadig ønsker at tjekke for det just in case, og det særlige værdi, GetString, svar og andre funktioner vender tilbage hvis noget er gået galt, er NULL i alle hætter. Og hvad er NULL? NULL bare så sker for at repræsentere en pegepind. Det er hukommelsen adresse 0. Verden besluttede, at vilkårligt, hvis dette er min computers hukommelse - ved du hvad? - vi kommer til at stjæle bare 1 byte af hver computers hukommelse, og det er placering 0. Vi vil give det et kaldenavn for NULL, og vi vil love at vi aldrig vil faktisk sætte reelle data der fordi vi netop vilkårligt brug for en særlig værdi, 0, aka NULL, så vi kan råbe på brugerne, hvis noget går galt. Ellers kan du måske ikke ved er 0 betyde sætte noget her eller betyder det noget gik galt? Vi er nødt til alle enige om, at NULL betyder intet blev returneret, nogen egentlig adresse blev returneret. Nu, her er jeg bare vedtage mit menneskelige konvention af jeg vender tilbage 1 fra main hvis noget går galt. Det er fordi main tilbagevenden konvention er at vende tilbage 0 hvis gode, 1 eller en anden værdi, hvis dårlige. Men GetString og enhver funktion, der beskæftiger sig hukommelsen returnerer NULL hvis noget går dårligt. Okay. Så desværre linie 27, super simpelt selv om det er helt undlader at kopiere strengen. Hvorfor? Vi kan se dette som følger. Jeg påstår på linje 27 til at lave en kopi af s og kalder det t. Så jeg beder ikke brugeren om 2 strenge denne gang, jeg siger bare værdien i s bør sættes i t så godt. Så nu bare at vise, hvordan brudt dette er i linie 29 og fremefter hvad gør jeg? Først Jeg tjekker, om længden af ​​t er større end 0. Der er nogle streng der. Brugeren har indtastet noget i. Hvad er linie 32 gør, tilsyneladende? [Uhørlig student svar] >> Højre. Du kan slags udlede det fra hvad jeg sagde, at det gør. Men teknisk set, hvad det gør? t [0] repræsenterer hvad? [Studerende] The 0:e karakter. >> [Malan] The 0:e karakter. Eller mere menneskelignende, det første tegn i t, hvad det så end er, H måske i dette tilfælde. Og toupper gør hvad den siger. Det kapitaliserer 0:e karakter t og det ændrer det. Så det betyder at den nulte karakter t, gøre det store bogstaver, og læg den tilbage i det samme sted. Så hvis jeg skriver hej med små bogstaver, bør dette ændre det lille h til en kapital H. Men problemet er, at i linjerne 35 og 36, hvad jeg er ved at gøre, er at printe ud for os s og t. Og hvad er din fornemmelse? Hvad skal jeg faktisk kommer til at se, om jeg har skrevet i hej i alle små bogstaver? Hvad skal der blive udskrevet? >> [Uhørlig student svar] >> Hvad er det? [Studerende] Big H og resten lille. >> Den store H og resten lille til der,? S eller t [Studerende] Begge. >> Begge. Præcis. Så lad os se hvad der foregår her. Lad mig gå videre og kompilere dette. Det er Kopi1, så gør Kopi1. Ok. Zoom i. Lad mig gå videre og køre Kopi1, Enter, Sig noget: hej med små bogstaver. Det kapitaliserede kopien, men det tilsyneladende kapitaliserede originalen så godt, fordi hvad nu sker i denne historie? På linje 27 jeg faktisk ikke synes at være at kopiere strengen, men selvom du måske har intuitivt håbet, at at være tilfældet, hvis du tænker over dette billede, hvad der virkelig har jeg gjort? Halvdel af billedet er den samme. Så lad os rulle tilbage i tiden, så t endnu ikke eksisterer i historien. S kan eksistere i historien, men lad os små bogstaver hej denne gang. Så lad mig ordne det, jeg faktisk skrevet i. I dette tilfælde her har vi h-e-l-l-o. Vi vil tegne den som en sekvens af tegn, sætte mine separator linjer her og min \ 0. Så dette er, hvor vi er, så snart linie 1 til 24-ish, give eller tage, har henrettet. Det er det billede af min hukommelse. Når jeg kommer til linie 27, hvad sker der? Ligesom før, får jeg en pointer, som jeg vil trække da dette torv. Det hedder t. Og hvad er dens værdi som standard? Hvem ved? Nogle garbage værdi. Så jeg vil abstrakt, at væk som et spørgsmålstegn. Og så snart den højre side af linien 27 udfører, hvad skal jeg sætte indersiden af ​​t? Det samme ting, der er i sek. Så hvis vi for et øjeblik fjerne denne abstraktion af pilen, og vi siger, åh, det er memory load adresse 123, når du siger t får s, semikolon, du bogstaveligt talt at sætte 123 her. Nu, hvis vi slags forenkle vores verden igen med billeder, hvad du har virkelig gjort, er blot tilføjet en anden pil til din verden der peger fra t til nøjagtig de samme streng. Så når i linje 31 og 32 jeg faktisk gå om at ændre t [0], hvad er t [0] tilsyneladende synonymt med nu? s [0] Så det er alt, hvad der sker. Og selvom den slags føles lidt lavt niveau og arcane og denne slags føles som måske intuitivt dette bør har netop arbejdet - Jeg har lavet kopier af ting før, og det fungerede bare - hvis du rent faktisk tænker over, hvad en streng egentlig er, det er en char *. Nå, hvad er det? Det er adressen på nogle tegn. Så måske giver det mere mening, at når du forsøger at gøre noget super tilsyneladende simpelt som dette, alt hvad du laver, er at kopiere en hukommelse adresse. Du er ikke faktisk gør noget med selve strengen. Så selvom du ikke har nogen idé om, hvordan du ville løse dette problem i kode, højt niveau, begrebsmæssigt, hvad vi skal gøre for at gøre ta tro kopi af s, tilsyneladende? Yeah. >> [Studerende] Giv det en ny placering? >> Præcis. Vi er nødt til at give t et helt nyt sted. Vi har brug for en eller anden måde skabe en verden, hvor vi får en ny bid af hukommelse, der bare for klarhedens skyld vil jeg trække lige under denne ene, men det behøver ikke at være der. Men det skal være den samme størrelse, så jeg vil tegne disse lodrette linier i det samme sted. Det er fint, hvis det er alt skrald i første omgang. Hvem ved, hvad var der? Men trin 1 vil være nødvendigt at give mig så meget hukommelse som jeg har brug for til at passe en kopi af hej, så finde ud af at kopiere h her, e her, på l her og så videre. Men dette allerede burde føle sig lidt indlysende, selv om nogle af detaljerne er stadig abstrakte. Hvis du vil kopiere denne streng ind i dette, det er bare en for-løkke eller en while-løkke eller noget, som du er blevet endnu mere kendte. Så lad os prøve dette. Lad mig gå ind i copy2.c. I copy2.c vi har næsten det samme program, bortset fra linje 27. Det ser lidt kompliceret, men hvis vi bryder den ned stykke for stykke, den venstre side er den samme. Char * t skaber denne ting i hukommelsen, men med et spørgsmålstegn fordi vi ikke har nogen idé om, hvad er der som standard. På den højre side er vi nu ved at indføre en ny funktion, malloc, for hukommelse tildele, giv mig hukommelse, og det tilsyneladende tager, hvor mange argumenter, hvor mange ting i parenteser? Jeg hørte murren i 1 og 2, men det er kun 1. Der er ingen komma, hvilket betyder, at der er kun 1 ting i parenteserne. Selv om der er andre parenteser, lad mig fremhæve hvad der er inde i den yderste parenteser, og det er dette udtryk: (Strlen (s) + 1) * sizeof (char). Så hvis vi tror faktisk dette igennem, er dette siger give mig længden af ​​s. Hvorfor er jeg dog tilsætte 1 på længden? >> [Uhørlig student svar] Præcis. Vi har brug for plads til denne fyr i halen, det sjette tegn, der ikke har nogen engelske betydning men har særlig programmatiske betydning. Så vi har brug for en + 1 for at fordi strlen returnerer den menneskelige forventning af længde, Hej eller 5, betyder det ikke give dig den ekstra null-tegn. Så jeg manuelt tilføje dette med + 1. Og så dette, * størrelse (char), har vi ikke set det før. Dette er ikke teknisk set en funktion. Det er en speciel søgeord, der bare fortæller dig, hvad størrelsen er af nogle datatype på en computer for i virkeligheden, har nogle af os 32-bit computere. Jeg har en temmelig gammel computer derhjemme, og det kun anvender 32 bits til at repræsentere pointers. Og så hvis jeg gjorde størrelse med en datatype, kan det være 32 bit. Men hvis jeg bruger min nye fancy computer, kan jeg komme tilbage en værdi på 64 bits for noget som en adresse. Så i dette tilfælde, at bare være super sikker, vi vil ikke til hårdt kode noget lignende - godt, hvad er på størrelse med en char efter hvad vi har sagt indtil videre? Vi har stort set sagt mundtligt, at det er 1 byte, og det er temmelig meget sandt over hele linjen. Men igen, antagelser tendens til at være dårlig. De fører til buggy software, hvis folk bruger din software på måder, du ikke havde til hensigt. Så lad os abstrakt dette væk og bare mere generisk sige Jeg har brug for så mange bidder af hukommelse og hvert stykke af hukommelsen skal svare til størrelsen af ​​en karakter, der er faktisk lig med 1 i dette tilfælde, men det er en mere generel måde at skrive det. Så hvis ordet er hej, hvordan mange bytes malloc tilsyneladende tildele for hej? [Studerende] Six. >> Six. Præcis så mange, som vi har spørgsmålstegn på skærmen. Og så tage et gæt nu baseret på din forståelse af GetString hvad betyder malloc sandsynligvis vende tilbage? >> [Studerende] En adresse. En adresse på hvad? Af de første bid af hukommelse. Vi har ingen idé om, hvad der er der, fordi en anden funktion kunne have brugt denne hukommelse tidligere. Men malloc, som GetString, returnerer adressen af ​​den første byte hukommelse at det har afsat til dig. Men hvad den ikke gør udfylde dette emne med en backslash null-tegn fordi det viser sig, du kan bruge malloc at allokere noget: Ints, strygere, arrays, flåd, studerende strukturer. Du kan bruge malloc helt generisk. Det er ligeglad med eller have at vide, hvad du tildele hukommelse til. Så det ville være formasteligt for malloc at sætte en \ 0 ved slutningen af ​​hver bid af hukommelse det er at give dig fordi dette \ 0 ting er bare en konvention for strygere. Det er ikke brugt til int'er, er det ikke anvendes til flåd, er det ikke bruges til studerende. Og så gotcha med malloc er, at byrden er helt på dig programmeringsenheden at huske, hvor mange bytes du tildelt og ikke at nogensinde bruge en for-løkke eller en while-løkke og gå forbi grænsen for bid af hukommelse, du har fået. Sagt på en anden måde, så snart du allokere hukommelse, du kan ikke bede operativsystemet, åh, forresten, var hvordan store af en luns af hukommelse dette? Det er helt op til dig at huske, hvis du har brug for denne værdi. Så lad os se, hvordan jeg fortsætte med at bruge denne hukommelse. På linje 28 og 29, hvorfor gør jeg dette? Bare total tilregnelighed check. Bare i tilfælde af at noget gik galt, jeg bede om nogle vanvittige mængde hukommelse eller jeg har så mange ting, der kører på den computer, der er bare ikke nok hukommelse, sådan noget, jeg i det mindste ønsker at tjekke for null. I virkeligheden vil de fleste computere giver dig den illusion, at ethvert program kan bruge hele din RAM, men alligevel, hvis brugeren skriver i nogle skøre lang snor måske fordi de er en dårlig fyr og de er faktisk forsøger at gå ned dit program eller hacke sig ind på det, du ønsker at i det mindste kontrollere returværdien af ​​malloc, og om det er lig nul. Og hvis det gør, lad os bare afslutte lige nu, fordi jeg ikke ved, hvad de skal gøre i dette tilfælde. Hvordan kan jeg kopiere strengen? Der er et par måder at gøre dette. Der er str kopiere funktioner i C, men det er super nemt for os at gøre dette den gammeldags måde. Først lad mig regne ud, hvad længden af ​​s er. Jeg kunne have sat dette i løkken, men i stedet jeg bare sætte det ud her for klarhed. Så n nu lagrer længden af ​​den oprindelige streng, som tilsyneladende 5. Så i min for-løkke, jeg iteration fra 0 på op til n, og på hver iteration jeg lægger s [i] indersiden af ​​t [i]. Så det er hvad jeg underforstået med mine 2 fingre peger på strengene før. Da dette for-løkke gentages som denne, vil jeg være kopiering h ind på her, e ind på her, l ind her, fordi det er s, det er t. Og så endelig, på linje 35 hvorfor gør jeg dette? Jeg er nødt til at sørge for, at jeg slutter strengen t. Og jeg gjorde det på denne måde at være super eksplicit. Men foreslå nogen, hvis man kunne, en anderledes måde at gøre dette. Jeg har ikke rigtig brug linie 35. Der er en anden måde at gøre dette. Yeah. >> [Uhørlig student svar] >> Sig det højere. [Studerende] Mindre end eller lig med. >> Præcis. Vi kunne blot sige mindre end eller lig med n, som generelt har været dårlig fordi næsten altid, når vi går op til en lige til de ting, vi tælle vi gå 1 skridt for langt. Men husk, hvor mange bytes vi tildeler? Vi tildelte strlen af ​​S, SO 5 + 1 for i alt 6. Så i dette tilfælde kunne vi gøre noget som dette så vi kopierer ikke bare den goddag, men også den \ 0 til allersidst. Alternativt kunne vi bruge en funktion kaldet str kopi, strcpy, men det ville ikke være nær så meget sjov. Men det er alt det gør under kølerhjelmen. Så endelig gør vi det samme som før. Jeg udnytte t og så har jeg hævder, at den oprindelige ser sådan her ud, og kopien ligner det. Så lad os prøve det nu. Lad mig gå ind her. Gør copy2. Vi zoome ind og køre copy2. Jeg har tænkt mig at skrive hej med små bogstaver, og ja, jeg får små bogstaver hej som den oprindelige men kapital Hej for kopien. Men jeg er ikke færdig endnu. Jeg er nødt til at gøre 1 sidste ting her. 46 og 47 er klart frigøre hukommelse, men hvad betyder det egentlig? Hvad laver jeg, tror du, ved at kalde linie 46 og linie 47? Hvilken effekt har det have? Yeah. [Uhørlig student svar] >> Præcis. Du er bare at fortælle operativsystemet, hey, tak for denne hukommelse. Du kan nu bruge det til en anden. Og her er et perfekt eksempel på skrald værdier. Jeg har netop brugt denne hukommelse til at skrive ned ordet hej i 2 steder, her, her, her og her. Så dette er h-e-l-l-o-\ 0. Men så kalder jeg linie 46 og linie 47, og du ved, hvad der sker der i forhold til billedet? Faktisk, vent, dette billede er det gamle. Når vi gøre kopien, er denne fyr faktisk peger her, så lad os fjerne de numre og bare abstrakt væk som vores pile igen. Hvad sker der i dette billede, når jeg ringer gratis? [Uhørlig student svar] >> Ikke engang. Hvis jeg ringe gratis på s og t - slags en trick spørgsmål - dette billede ændrer sig ikke på alle fordi kalde s og kalde t bare fortæller operativsystemet, hey, kan du bruge denne hukommelse igen, men det ændrer ikke dette til null eller nogle specialtegn, ændrer det ikke dette, det ændrer ikke h eller e eller l, eller l, eller o i enten sted til noget andet. Med hensyn til billedet,. Så snart du kalder gratis, intet ændres Og deri ligger oprindelsen af ​​skrald værdier, fordi hvis jeg så senere i dette program bede operativsystemet for mere hukommelse med GetString eller malloc eller noget i den stil og operativsystemet siger, sikker, jeg har 12 bytes hukommelse bare frigøres, bruge disse, hvad vil skal afleveres? Du kommer til at blive udleveret en bid af hukommelse, som vi typisk ville trække med spørgsmålstegn, men hvad er de spørgsmålstegn? De befinder sig h-e-l-l-o, h-e-l-l-o. Det er vores nye skrald værdier så snart du frigøre den hukommelse. Der er en virkelig verden antydes her også. Dette sker for at gøre med RAM, men dine computere rent faktisk gør det samme med disk. Vi vil tale om dette, navnlig med et fremtidigt problem sæt, der fokuserer på retsvidenskab. Men hvad sker der egentlig, hvis du har nogle følsomme finansielle fil på skrivebordet eller nogle sketchy JPEG og du trækker det ind i din papirkurv, hvad der sker, når du trækker det i skraldespanden eller papirkurven? Du vidste, hvad jeg talte om. [Latter] Hvad sker der, når du har trukket disse beviser til din papirkurven eller papirkurven? [Uhørlig student svar] Nå, så pas på. Hvad sker der, når du gør det? Det korte svar er intet, right? Sketchy eller følsomme sag er stadig bare sidder der et eller andet sted på din harddisk. De fleste af os i det mindste har lært på den hårde måde, at du skal tømme din papirkurv eller din papirkurven til rent faktisk at slette filer. Og ja, når du højreklikker eller Control klik på din skraldespand eller vælg Filer, Tøm papirkurv eller hvad og du faktisk tømme papirkurven eller papirkurven, hvad der rent faktisk sker der så på dette billede? Mere intet. Så intet rent faktisk sker på disken. Og hvis vi bare midlertidigt sidespring og skrive - æ bare bruge bagsiden af ​​denne. Så nu historien ændrer sig fra RAM, hvilket er hvor programmer findes mens du kører dem til disk, som er hvor de er gemt på lang sigt selv når strømmen går ud, for nu - og vi vil komme tilbage til dette i fremtiden - lad os bare lade som om, at dette repræsenterer harddisken inde i din computer fordi tilbage i dag, de plejede at være cirkulære diske, meget gerne disketter. Så hvis du har nogle følsomme Excel-fil, kan det tage op denne luns af hukommelse på computerens harddisk, og jeg er bare tegning samme vilkårlig 1s og 0'erne. Når du trækker filen gerne have, at din skraldespand eller papirkurven, bogstaveligt talt intet sker, fordi Apple og Microsoft netop har besluttet papirkurven og papirkurven er egentlig bare en midlertidig pladsholder. Måske i sidste ende OS vil tømme det for dig, men typisk, at det ikke gør noget, i hvert fald indtil du er virkelig lav på plads. Men når du går til Tøm papirkurv eller Tøm papirkurv, Ligeledes sker der ingenting til dette billede. Alt, hvad der sker, er et andet sted på din computer, er der en slags bord. Det er lidt ligesom en lille snyde ark, der siger, at, lad os sige, resume.doc, så dit cv i et Microsoft Word-fil bruges til at leve i position 123 på harddisken, ikke i hukommelsen og ikke i RAM, men på harddisken, og dine sketchy JPEG liv på 456, og din Excel-fil bor på 789 eller andre steder. Når du sletter filer ved faktisk tømme papirkurven eller papirkurven, dette billede ændrer sig ikke. Den 0'er og 1-taller på din harddisk ikke gå nogen steder. Men denne tabel, denne lille database slags, ændrer sig. Når du sletter dit cv, er det som om filen er slettet i en eller anden forstand, men alt computeren gør, er at glemme, hvor den ting lever på din harddisk. Den 0'er og 1-taller, der komponere dit CV eller en af ​​de andre filer er stadig intakt. Så hvis du gjorde det ved et uheld, er der stadig en ikke-nul sandsynlighed at du kan gendanne dine data ved hjælp af Norton Utilities eller nogle kommercielle software hvis formål i livet er at finde 0'er og 1-taller, der er slags blevet forældreløse, glemt her, men forlod her, så du kan få dine data tilbage. Eller retsmedicinske efterforskere med politiet eller FBI ville faktisk tage en harddisk og faktisk se efter mønstre af 0'er og 1-taller, der ligner JPEG, ligner Excel-filer, og gendanne dem på den måde, selv hvis computeren har glemt dem der. Så den eneste måde virkelig at slette data, som vi vil diskutere i fremtiden, er at skrubbe eller tørre filen eller harddisk ved - Du kan ikke rigtig slippe af med 0'er og 1-taller fordi ellers du ville starte med en gigabyte harddisk og du vil ende op med en megabyte harddisk, hvis du hele tiden var slette, bogstaveligt, 0'er og 1'ere. Så hvad ville du gøre, hvis du virkelig ønskede at dække dine spor og det grundlæggende problem er, at der stadig er 0'er og 1-taller på disken? Jeg ser nogen gestikulerende, at du fysisk ville bryde enheden. Det vil virke. [Latter] Men hvis det er sådan en dyr løsning, hvad ville være mere rimeligt? Yeah. >> [Studerende] Overskriv dem. >> Overskriv dem med hvad? >> [Studerende] Andre data. Andre data. Du kan bare overskrive disken med 0'er eller 1'er eller 0'er, alle 1s. Og det er faktisk, hvad nogle af softwaren gør. Du kan købe software eller endda få gratis software, og endda indbygget i Mac OS disse dage, i mindre grad i Windows, er evnen til sikkert at slette. Faktisk, hvis du ønsker at alle køre hjem i dag, hvis du har en Mac og gør dette, hvis du har fået nogle ting i din papirkurv kan, kan du gøre Sikker tømning af papirkurv, som gør netop dette. Snarere end blot slette filer her, betyder det ikke slette den 0'er og 1'ere her, snarere, det bare ændrer dem alle, for eksempel, til 0'er og prik, prik, prik. Så en af ​​dine fremtidige psets rent faktisk vil være til forsætligt gendanne data - billeder, vi har taget af mennesker, steder og ting på campus som vi vil gøre en retsmedicinsk billede af et digitalt kameras hukommelseskort, som er den nøjagtige samme idé - og du bliver nødt til at blive udfordret til rent faktisk at finde de mønstre, der repræsenterer JPEG på din harddisk, meget gerne, at tidligere studerende, hvis e-mail jeg læste et par uger siden gjorde at genvinde sin søsters fotografier. Hvorfor tager vi ikke en 5-minutters pause her, og vi vil omgruppere med mere på hukommelsen. Så her er, hvor tingene bliver lidt hjernevridende, men dette er en meget kraftfuld skridt mod en forståelse dette så meget mere. Her er et program kaldet pointers.c. Det er blandt dagens prøve kode. Bemærk, at i de første par linjer, 19 til 22, alt, hvad vi laver, er noget som GetString og returnere en adresse, gemme det i sek. Fremover for Pset selv 3, hvis du vil, men Pset 4 og på hvor du kan begynde at tage disse støttehjul off dig selv, Der er ingen grund til at foregive, at strengene eksisterer længere. Det er helt sikkert i orden at bare begynde at sige char *. Som en sidebemærkning, du i online referencer og i bøger kan ofte se på stjernen ud for variablen. Du kan endda se mellemrum omkring begge sider af det. Alle af dem er funktionelt korrekte. For nu, selv om vi standardisere på denne fremgangsmåde for at gøre super klar at char * er som at sige karakter pointer. Det er den datatype. Og så navnet på den variabel er s i denne sag. Så vi har fået en streng, og vi har kaldt det s. Og så hernede bemærke, at jeg gør faktisk en lille smule af svindel. Dette kaldes pointer aritmetik, som er en slags super enkel. Det betyder bare lægge sammen og trække numre til pegepinde. Men det rent faktisk virker. Dette program tilsyneladende udskriver strengen s 1 tegn pr linje, således at slutresultatet - Bare så vi kan forkæle hvor dette foregår, lave pointere, køre pointere, lad mig zoome ind Lad mig skrive noget lignende HELLO og type Enter og den udskriver 1 karakter per linje. Indtil for et øjeblik siden, ville vi have gjort det med firkantet beslag notation. Vi ville have en for-løkke, og vi ville gøre printf af s [i], og vi ville gøre det igen og igen og igen med en backslash n for enden af ​​hver linje. Men dette program er anderledes. Dette program bruger, bogstaveligt talt, aritmetik. Så hvad sker der her? Først og fremmest, før denne sløjfe selv udfører, hvad, bare for at være klar, er s egentlig? S er? >> [Studerende] En adresse. >> En adresse. Og det er den adresse, der er tale om hello, det første tegn i det ord, der er timer. Så s er i dette særlige eksempel, adressen på timer. Så hvad betyder det at gøre s + i? Nå, jeg starter ved 0 i dette for-løkke. Vi har gjort det mange gange. I kommer til at gå op til længden af ​​strengen, tilsyneladende. Så på den første iteration af denne løkke, er jeg naturligvis 0. Så dette udtryk siger s + i - snarere, s +0--det er naturligvis lige s. Så hvad er * s her? Nu bruger vi stjernen i en lidt anden måde. Lad mig gå videre og slippe af t, fordi vi er færdige taler om t og kopier af s. Nu skal vi bare ønsker at fortælle en historie, der involverer s. Og så i dette øjeblik, efter at have typen string, ser vores verden helt ligesom det gjorde før med bare s lagring adressen på h og mere generelt peger på strengen hej. Hvis jeg nu gøre en linje som * (s + i), lad os prøve dette. Så * (s + i). Lad mig forenkle dette, fordi det er 0, så det er * (s +0). Tja, vent lige lidt. Forenkler yderligere. Dette er * (s). Nå, nu parenteserne er slags dumme, så lad os nu bare gøre * s. Så i den første iteration af denne løkke, denne linje, der er markeret, 26, er temmelig meget svarende til udskrivning dette. Hvad er datatypen for * s? I denne forbindelse, fordi stjernen tilfældigvis er ved siden af ​​s selv, men mere specifikt, fordi vi ikke længere erklære s, vi ikke skabe en variabel længere, er der ingen omtale af char * i linje 26, Der er ingen omtale af søgeordet strengen, er vi bare bruge en variabel kaldet s, Det viser sig nu stjernen har lidt anderledes og ganske vist forvirrende betydning. * S betyder her at gå til adressen i s og print, hvad der er der. Så s er her, * s er - lidt ligesom Chutes and Ladders, følg pilen - her. Så det er * s. Så hvad bliver udskrevet på den første iteration af denne løkke i linje 26? Jeg udskrive% c, som er pladsholder for en karakter, derefter en \ n for en ny linje. * (S + i) hvor i er 0 er netop dette. Så hvad char skal jeg placere i for% c? H. I den næste iteration af løkken - du kan sandsynligvis se, hvor dette foregår - den næste iteration i er naturligvis 1, så betyder s en, og så nu jeg har brug for parenteserne, for nu stjernen nødt til at sige gå til hukommelsesadresse s +1. Hvad er s? Lad os rulle tilbage i tiden og sige dette pil nu er faktisk ikke gør os nogen tjeneste. Lad er mere specifikt sige, at dette er lagring af antallet 123 idet starten af ​​denne streng hallo, er adressen 123, er 124, og så videre. Så på den anden iteration når jeg siger s +1, er det ligesom at sige, 123 1, ellers kendt som 124, så hvad char bliver trykt på den anden iteration? E på hukommelsesadresse 124. Så + igen, 125, 126, 127, og denne løkke heldigvis stopper før vi får her fordi jeg bruger strlen at sikre, at jeg ikke tæller for højt. Så det er også det. Igen, det er bare som om vi havde gjort en uge siden. Lad mig skrive det på linjen nedenfor, selvom vi ikke ønsker at gøre begge dele. Dette er identisk nu til dette. Så selvom s er en streng, som vi har kaldt det for uger, s er virkelig en char *. Så hvis vi ønsker at være super anal, det er virkelig rigtigt at skrive den særlige karakter på den i'te placering ved hjælp af disse numeriske adresser og denne stjerne operatør, men helt ærligt, det er bare så meget renere. Så det er ikke dårligt. Ingen grund til at stoppe med at gøre linje 27 her, men 26 er funktionelt det samme, og det er funktionelt det samme for præcis de grunde, vi har diskuteret hidtil. Og endelig 29 er bare god praksis. Opkald fri for s betyder, at nu er du give tilbage den hukommelse, som GetString gav dig fordi igen, da jeg nævnte mandag, GetString i ugevis har været at indføre en fejl i din kode. Din kode i ugevis har haft memory leaks hvor du har bedt GetString for hukommelse, men du har aldrig været at give det tilbage. Og det blev bevidst valgt af os pædagogisk fordi det er bare for meget at tænke på et tidligt tidspunkt. Men nu har vi brug for mere symmetri. Hvis du beder computeren om hukommelse, som det er tilfældet for GetString, som det er tilfældet tilsyneladende for malloc, Du skal nu til Pset 4 og frem også gratis en sådan hukommelse. Bemærk dette er forskelligt fra at sige int n. Du behøver ikke at befri dette, fordi du ikke kalde GetString og du ikke kalde malloc. Og selv hvis du kaldte GetInt som vi i sidste ende vil se, GetInt ikke tildele hukommelse til dig, fordi du rent faktisk kan passere rundt heltal og flåd og specialtegn bare den måde, vi har gjort i ugevis. Strygere, selv om, er specielle, fordi virkelig de er den sammenkædning af flere tegn. Så de er bare forskellige fra chars og flåd og Ints og lignende. Men vi vil vende tilbage til det inden længe. Eventuelle spørgsmål derefter på denne begyndelse af pegepinde? Yeah. [Uhørlig student spørgsmål] Ah, meget godt spørgsmål. En af de få ting, C faktisk gør for dig, hvilket er praktisk, er det tal ud for dig, hvad størrelsen er af datatypen og derefter gør den slags multiplikation for dig. Det er irrelevant i tilfælde af tegn, fordi næsten altid en char er 1 byte, så dette virker bare. Men af ​​hensyn til diskussion, hvis du rent faktisk var ved at udskrive heltal og du prøvede at udskrive en vis værdi s, der pegede mod et heltal, du ligeledes ville ikke behøver at gøre + 4 * jeg bare fordi en int er 4 bytes. Pointer aritmetiske betyder, at C og compiler gøre alt, matematik for dig. Alt du skal bekymre sig om, er optælling i form af den menneskelige fornuft. Yeah. [Studerende] Hvis du erklærer en streng inde i en for-løkke, behøver du nødt til at befri det senere? Godt spørgsmål. Hvis du har erklæret en streng inde i for-løkken, har du brug for at frigøre det senere? Du behøver kun at frigøre hukommelse, som du tildeler med GetString eller med malloc. Så hvis du bare sige noget lignende - lad mig sige krøllede parenteser nu så al koden er relateret. Hvis du gjorde noget, omend buggily, som dette, char * t = s, du behøver ikke at gratis t fordi t ikke indebar nogen omtale af malloc eller GetString. Hvis derimod du gjorde dette, GetString, så ja, ville du nødt til gratis t. Og i virkeligheden er din eneste chance for at gøre det nu inde i denne løkke, for samme nummer af anvendelsesområdet at vi har diskuteret tidligere. Ellers ville du være allokering af hukommelse, allokering af hukommelse, tildele hukommelse, og ved afslutningen af ​​programmet, fordi du er uden for denne løkke, t eksisterer ikke, men du aldrig fortalt operativsystemet at du ikke behøver at hukommelsen længere. Og inden længe, ​​for Pset 4 eller 5 vil vi udstyre dig med et program kaldet Valgrind, som er ens i ånd med GDB i at det har fået lidt af en mystisk interface, men dens formål i livet er at hjælpe dig. Og Valgrind er et program, der i fremtiden vil søge i dine programmer udkig efter memory leaks, uanset om GetString eller malloc, som vi vil begynde at bruge så meget desto mere som vi holder op med at bruge CS50 biblioteket så meget. Vi endelig har nu slags det ordforråd og den slags mental model i teorien med til at løse dette brudte program. Så i denne brudt program, arbejder swap inde i swap, men det faktisk aldrig arbejdet i main fordi main gik i x-og y, recall, og dem, der blev vedtaget i af værdier, så at sige. Kopier af dem blev givet til at bytte. Ved udgangen af ​​swap, var a og b faktisk blevet udvekslet, men selvfølgelig x og y, som vi diskuterede i mandags, havde ikke været. Så jeg foreslår i grøn her, at dette er faktisk den løsning her. Og faktisk, lad mig flytte mine stjerner bare for at være i overensstemmelse selv om igen, funktionelt dette betyder ikke noget. I de kommende uger vil vi forklare, hvornår og hvorfor det betyder noget. Så i grøn nu er en løsning. Helt ærligt, det ser en hel masse Messier fordi jeg har alle disse stjerner. Lad mig påpege én ting. Den øverste linie her, hvor der står int * a og int * b fundamentalt gør det samme, som det altid har gjort. Det er at erklære 2 argumenter eller parametre at bytte, hvoraf den første er en int pointer kaldet en, hvoraf den anden er en int pointer kaldet b.. Det eneste, der er nyt på dette punkt er det faktum, at der er en stjerne der. Hvad betyder det? A er ikke en int, b er ikke en int. A er adressen på en int og b er adressen på en anden int. Hernede er det her, jeg indrømmer C bliver forvirrende. Nu vi bruger en stjerne, men det har forskellig betydning i denne sammenhæng. Fordi vi ikke er erklære pegepinde, som vi er heroppe, her er vi dereferere ting. Så teknisk set stjernen i denne forbindelse af den første, anden og tredje linje indersiden af ​​swap er dereference operatør, hvilket betyder bare derned. Så lige som min finger fulgte pilen til h, * Et middel gå til den pågældende adresse og finde mig int, der er der. * B midler gå til den adresse og passere mig hvad der er. Så lad os gentegne billedet fra mandag nu ved hjælp af en stak af frames, den nederste hvoraf bliver hoved, den øvre hvoraf bliver swap, så vores verden ser ud, ligesom mandag som denne. Her er en bid af hukommelse, main skal bruge. Recall fra mandag, at programmet netop havde 2 variabler, en der hedder x og en kaldet y, og jeg havde lagt tallene 1 og 2 er der. Nu når jeg kalder bytte ligesom jeg gjorde i mandags, tidligere, da jeg brugte den røde version af dette program, som ser sådan ud, Jeg fik 2 parametre, A og B, og hvad gjorde vi skriver her og her? Blot 1 og 2, bogstaveligt talt kopier af x og y. I dag har vi ændre det. Dag i stedet for at passere i int'er a og b vi kommer til at passere i 2 adresser. Disse adresser tilfældigvis til at pege på int'er, men disse adresser ikke Ints sig selv. De er adresser. Det er ligesom en postadresse i stedet. Så nu er vi nødt til at bare give mig en lidt mere detaljeret på skærmen. Dette er min computers hukommelse som det har været hele dagen. Nu har vi brug for nogle vilkårlig nummersystem. Så lad os bare sige, blot ved en tilfældighed, at det er memory-adresse 123, 124. Lad os bare sige det er 125, det er 126, og så videre, men det er helt vilkårlig. Vi skal bare have nogle nummereringsskema i min hukommelse. Så nu når jeg rent faktisk går i x og y, jeg ikke kommer til at passere i x og y; Jeg har tænkt mig at passere i den postadresse, så at sige, af x og y så det, der bliver gemt her, og her er ikke 1 og 2, men hvis du kan se min lille tekst, bliver hvad gik i her og her? [Uhørlig student svar] >> Præcis. 123 bliver sat her og 124 bliver sat her. Nu, fordi jeg brugte stjernen i denne allerførste linje op her på toppen, mit program bare ved, at 123 og 124, selv om de er tydeligvis heltal at noget menneske kunne mærke, skal de fortolkes som adresser, numeriske adresser. De er ikke i sig selv int'er, de er adresser, og det er fordi jeg udtrykkeligt har sat stjerner der. Så nu i min første, anden og tredje linje af faktiske kode, hvad der sker her? Lad os trække resten af ​​billedet. Tmp er ligesom det var i mandags. Intet særligt om tmp. Det er blot et lokale 32 bit variabel, og indersiden af, at jeg åbenbart lagring af værdien af ​​* en. Nu, hvis jeg sagde bare tmp = a, hvad ville jeg have her? >> [Studerende] 123. 123. Men det er ikke hvad jeg laver. Jeg siger tmp = * en. Stjernede midler derned. Så her er en, 123. Hvordan kan jeg gå der? Foregive som om der er en pil. Tja, der er det, 1. Så hvad bliver gemt i tmp, tilsyneladende? Bare 1. Så med andre ord, tmp er * A, * a midler gå til den adresse, der er i øjeblikket i en, som tilsyneladende 123. Okay, her er vi i position 123, ser jeg nummer 1, så jeg har tænkt mig at sætte nummer 1 der. Nu hvad gør jeg på linje 2, * a = * b? Denne ene er lidt mere involveret, fordi nu, hvad er en? Det er 123. Så * en er hvor? Lige hvor jeg var før. Så går der. Okay. Nu, endelig, og så endelig vil begynde at give mening, forhåbentlig, * B betyder hvad der er i b? 124. Så jeg er nødt til at gå der, hvilket er 2. Så hvad skal jeg sætte hvor? 2 går ind her, fordi * b går ind * en. Så jeg vil gøre det. Og du kan allerede se, måske, at vi er så meget tættere til at løse dette dumme, simple problem korrekt for første gang fordi nu har vi stadig en erindring om, hvad x var, vi har 2 kopier, ganske vist af y, men linje 3 nu siger * b. Så her er b. * B betyder derned. Så hvor er placering 124? Det er åbenbart her. Så hvad skal jeg have her? Naturligvis, tmp. Så nu gør jeg det. Så jeg har 1 her og 2 her. Og hvad nu om alt dette, 123, den 124, og 1? Så snart swap vender tilbage, denne hukommelse er så godt som tabt fordi så snart swap vender tilbage, operativsystemet er gratis at bruge, at hukommelsen igen i fremtiden. Kun main hukommelse i bunden af ​​denne såkaldte stak pinde rundt. Og så har vi endelig har nu en fungerende version. Lad mig gå ind i swap.c, og bemærk følgende. På toppen af ​​det program, jeg har ændret min prototype til at være int * a og int * b. Så det eneste, jeg skiftede til at gå fra rød, som var dårligt, til grøn, hvilket er godt, er jeg tilføjet disse stjerner i dag. Men så hernede i swappen selv jeg var nødt til at kopiere, indsætte, hvad der var lige på diaset. Jeg har en stjerne her, stjerne her - der matcher prototype - og så alle disse ting har nu stjerner bortset tmp fordi anvendelsen af ​​en midlertidig variabel, er der intet nyt der. Jeg skal bare have midlertidig lagerplads til en int. Så vi har ikke brug for en stjerne der. Vi skal bare bruge stjernen, så vi kan krydse denne form for vilkårlig grænse mellem disse 2 frames i min computers hukommelse. Men en sidste ting skal ændres, og du har måske ane det allerede. Hvilken anden linje er selvfølgelig anderledes nu? >> [Studerende] & x. Ja, så 25 er den sidste linje kode jeg nødt til at ændre for at dette virker. For en uge siden, og selv på mandag linje 25 lignede dette, bytte x og y, og dette var blot brudt, fordi hvis du siger swap (x, y) du giver kopier af x og y for at bytte, så det gør sin ting, men du er faktisk aldrig skiftende x og y selv. Så selv hvis du aldrig har set denne karakter før med tegnet i kode, bare tage et gæt. Hvad betyder tegnet gør, tilsyneladende? [Studerende] mener adressen. >> Mener adressen. Så tegnet siger give mig adressen på x. Hvem ved hvor det er? Det sker for at være 123. Jeg er ligeglad. Bare giv mig adressen på x. & Y betyder give mig adressen på y. Og på det tidspunkt, at historien er helt i overensstemmelse med det billede, vi trak et øjeblik siden. Så jeg vil indrømme pejlemærker, i hvert fald for mig, da jeg først begyndte at lære dette, var afgjort en af ​​de sværeste ting at ombryde mit sind rundt. Men indse, især da vi fortsætter med at spille med den slags ting, hvis du bryde det ned til disse super simple slags intellektuelt uinteressant problemer for bare at flytte numre rundt, svaret på en masse forvirring med pegepinde virkelig kan udledes af disse meget grundlæggende mekanik. Her er en adresse. Gå der med stjernen. Eller omvendt, her er et og-tegn. Regne ud, hvad adressen rent faktisk er. Ok. Så hvor er al denne hukommelse kommer fra? Vi har tegnet dette billede et par gange, og jeg holder lovende vi vil komme tilbage til det, men her er en repræsentation af computerens hukommelse det er lidt mere mærket end vores tavle her er. Teksten segment øverst repræsenterer, hvad med hensyn til dit program? [Uhørlig student svar] >> Undskyld? Sig det igen. [Studerende] Den faktiske program. >> Den faktiske program. Så den 0'er og 1-taller, at du har kompileret efter at have skrevet C-kode og derefter kører Dunk og generering af 0'er og 1-taller ender med at blive gemt der i hukommelsen fordi når du dobbeltklikker på et ikon på din Mac eller pc eller køre en kommando som mario på dit hurtige, din 0'er og 1'ere fra disk bliver indlæst i hukommelsen, så computeren kan manipulere dem og udføre dem hurtigere. Så klargjorte data og uden startværdi data, vil vi ikke snakke meget om dem, men de er bare globale variable. Initialiseret betyder globale variabler, som du gav værdier til; initialiseret betyder globale variabler, som du endnu ikke har giver værdier til. Så er der de miljøvariabler, som jeg vil helt bølge min hånd på, men de er der, og der gemmer ting som dit brugernavn og anden form for lavere niveau detaljer. Men de juiciest stykker af din hukommelse layout er denne ting kaldet stakken og bunke. Stakken igen, for at være klar, er hukommelsen, der bruges, når funktioner kaldes, hvis der er lokale variable og når der er parametre, der væltes rundt. Alt dette sker i stakken. Den bunke vi har ikke talt om, men tage et gæt, der bruger den bunke. Bare en anden luns af hukommelsen. Det sker for at blive trukket her øverst, men det er en vilkårlig billedlig konvention. Hvem tilsyneladende har brugt hukommelse fra bunke i flere uger? Det er teknisk dig, men indirekte. >> [Studerende] GetString. GetString og malloc. Så her er den grundlæggende forskel. Du kender i de sidste par uger, hvis du har brug hukommelse, bare erklære en variabel. Hvis du har brug for masser af hukommelse, erklære en array lige inde i din funktion. Men det problem, vi har holdt overfor, er, hvis du erklærer variabler lokalt inde i funktioner, så snart funktionen returnerer, hvad der sker med hukommelsen og disse variabler? Bare slags er det ikke længere din, ikke? Det bare forsvinder slags konceptuelt. Det er stadig fysisk der, naturligvis, men det er ikke længere din ret til at bruge. Det er selvfølgelig problematisk, hvis du ønsker at skrive funktioner i livet der faktisk allokere hukommelse og ikke give den tilbage med det samme. Sag i punkt: GetString formål i livet er at have nogen idé i forvejen hvor stor en streng jeg har tænkt mig at skrive på tastaturet, men det er nødt til at være i stand til at allokere hukommelse til at holde David eller goddag eller en hel essay, som brugeren måtte have skrevet i. Så GetString har brugt malloc. Malloc derfor skal bruge ikke stakken; I stedet er det ved hjælp af denne ting kaldet heap. Der er ikke noget anderledes ved hukommelsen. Det er ikke hurtigere eller langsommere eller noget i den retning. Det er bare fysisk et andet sted. Men reglen er, at den hukommelse, der er allokeret på heapen vil aldrig blive taget væk fra dig, indtil du ringer - tage et gæt - fri. Derimod dig nogen hukommelse bede om på stakken ved blot at erklære et array eller erklære en variabel ligesom vi har gjort i ugevis, at som standard ender på stakken. Og det virker godt 90% af tiden, men på de sjældnere lejligheder hvor du ønsker at allokere hukommelse og holde det rundt, så er du nødt til at bruge en funktion som malloc. Eller vi har brugt en funktion som GetString, som igen bruger malloc. Lad os se, hvor dette kan bryde ned og derefter tage et kig på Binky. Vi kommer tilbage til det i fremtiden. Her er et super simpelt program, der i de første 2 linier gør hvad? På engelsk, hvad de første 2 linjer kode gør inde i main? [Uhørlig student svar] Forsigtig. Det giver ikke mig adressen på x eller y. [Studerende] Giver henvisninger til int'er. >> Godt. Giv mig 2 pegepinde til heltal. Med andre ord, give mig 2 bidder af hukommelse, som jeg holder tegning i dag, selvom jeg slettet det nu, som firkanter. Giv mig 2 bidder af hukommelse, en kaldet x, en kaldet y - jeg tidligere kaldte dem s og t - og hvad er den type der bid af hukommelse? Det kommer til at gemme en adresse. Det er af typen int *. Så adressen på en int i sidste ende vil leve i x, adressen på en int i sidste ende vil leve i y, men i første omgang, hvad der er indeni af x og y? Hvem ved? Garbage værdier. Det har intet at gøre med pegepinde. Hvis vi ikke har lagt noget der, hvem ved hvad er faktisk der? Nu, x. Hvad sker der her? Dette er legit nu, fordi x er en pointer. Det er en int *. Så det betyder, at jeg kan sætte i x adressen på nogle bid af hukommelse. Hvad betyder malloc vende tilbage? Perfekt, returneres adresser, adressen af ​​den første byte i en hel bid af hukommelsen. Hvor mange bytes er dette tilsyneladende fordeling for eksempel i apparatet? Hvad er størrelsen af ​​en int? 4. Hvis du tænker tilbage til uge 1, er det ikke super vigtigt altid at huske, men i dette tilfælde er det nyttigt at vide, 4 byte. Så dette er fordeling på heapen 4 byte og det er tilbage adressen på den første til mig vilkårligt. Nu, hvad x laver? A * x = 42 gør hvad? Hvis der på dette tidspunkt i historien har vi x, der ser sådan ud med nogle skrald værdi, dette er nu y med nogle skrald værdi, nu i linie 3 Jeg har tildelt 4 byte. Dette billede væsentlige ligner dette. Eller mere specifikt, hvis dette er vilkårlig adresse 123, det er det, vores historie nu ser ud. * X = 42 betyder nu hvad? Det betyder gå til adressen 123 og sætte nummer 42 der. Jeg behøver ikke at tegne disse linjer, fordi vi ikke laver strenge. Jeg bør har netop skrevet det sådan her, og bare for demonstration skyld, 42 som en int slags fylder en masse plads, 4 byte. Så det er hvad der er sket der, men der er et problem nu. * Y = 13. Hvad vil der ske her? Problemet er * y i vores forenklede verden betyder bare gå til adressen i y. Hvad er der i y? Det er nogle skrald værdi. Så lad os antage, at det skrald værdi er 5551212, noget vanvittigt lignende. * Y midler til løse 5.551.212. Det er ligesom herovre. Det eksisterer ikke, for eksempel. Så * y får 13 betyder, jeg forsøger at tegne 13 her. Det findes ikke. Jeg har overskredet det segment af tavlen. Hvad får jeg? Denne kryptiske besked segmentering skyld, fordi jeg forsøger at sætte i hukommelsen en værdi som 13 på et sted, der ikke eksisterer. Resten af ​​programmet kan arbejde okay, men indtil da er det ikke. Så lad os prøve at fortælle denne historie. Vi vil vende tilbage til, at når vi har talt om hex. Lad os gå tilbage til dette og slutte af med denne ting kaldet Binky, som husker er en Stanford professor sidder derhjemme leger med claymation, at fortælle historien om netop det samme program. Det er bare omkring 3 minutter lang. Her har vi Binky. [Mandlig taler om video] Hey Binky, vågne op. Det er tid til pointer sjov. [Binky] Hvad er det? Lær om pointers? Oh, goody! [Mandlig taler] Tja, at komme i gang, jeg tror vi kommer til at bruge et par pointers. [Binky] Okay. Denne kode tildeler 2 pejlemærker, der kan pege på heltal. [Mandlig taler] Okay. Tja, jeg ser de 2 pegepinde, men de synes ikke at pege på noget som helst. [Binky] Det er rigtigt. I første omgang, behøver pointers ikke pege på noget som helst. De ting, de peger kaldes pointees, og sætte dem op er et separat trin. [Mandlig taler] Åh, højre, højre. Jeg vidste det. De pointees er adskilt. Is, så hvordan kan du tildele en pointee? [Binky] Okay. Denne kode tildeler en ny heltal pointee, og denne del sætter x til at pege på den. [Mandlig taler] Hey, det ser bedre ud. Så gør det gøre noget. >> [Binky] Okay. Jeg vil dereference markøren x for at gemme nummeret 42 i sin pointee. For dette trick jeg skal bruge min tryllestav af dereference. [Mandlig taler] Din tryllestav af dereferere? Det er godt. [Binky] Dette er hvad koden ser ud. Jeg vil bare oprette antallet og ... [Knaldende lyd] [Mandlig taler] Hey se, der det går. Så gør en dereference på x følger pilen for at få adgang sit pointee, i dette tilfælde til at gemme 42 derinde. Hey, kan du prøve at bruge det til at gemme nummeret 13 gennem den anden pointer, y. [Binky] Okay. Jeg vil bare gå over her til y og få nummer 13 oprettet og derefter tage staven fra dereferere og bare ... [Summende lyd] Whoa! [Mandlig taler] Oh hey, det virkede ikke. Sig, Binky, tror jeg ikke dereferere y er en god idé fordi oprettelsen af ​​pointee er et separat trin og jeg tror ikke, vi nogensinde gjorde det. [Binky] Hmm, god pointe. [Mandlig taler] Yeah. Vi tildelte markøren y men vi har aldrig sat den til at pege på en pointee. [Binky] Hmm, meget opmærksomme. [Mandlig taler] Hey, du ser godt ud der, Binky. Kan du lave det, så y peger på samme pointee som x? >> [Binky] Sure. Jeg vil bruge min tryllestav af pointer opgave. [Mandlig taler] Er det vil være et problem som før? [Binky] Nej, det betyder ikke røre pointees. Det bare ændrer en pegepind til at pege på det samme som en anden. [Knaldende lyd] [Mandlig taler] Åh, jeg kan se. Nu y peger på det samme sted som x. Så vent. Nu y fast. Det har en pointee. Så du kan prøve staven fra dereferere igen for at sende 13 over. [Binky] Uh, okay. Her går. [Knaldende lyd] [Mandlig taler] Hey, se på det. Nu dereferere værker på y. Og fordi de pejlemærker deler, at en pointee, de begge se 13. [Binky] Yeah, deling. Uanset hvad. Så skal vi skifte steder nu? [Mandlig taler] Oh look, vi er ude af tid. >> [Binky] Men - [Mandlig taler] Bare husk de 3 pointer regler. Nummer 1, den grundlæggende struktur er, at du har en pegepind og den peger hen til en pointee. Men markøren og pointee er adskilt, og den almindelig fejl er at oprette en pegepind men at glemme at give det en pointee. Nummer 2, pointer dereference starter ved markøren og følger pilen hen over at få adgang til sin pointee. Som vi alle ved, er dette kun fungerer, hvis der er en pointee, hvilken slags kommer tilbage til regel nummer 1. Nummer 3, pointer opgave tager en pointer og ændrer det at pege på den samme pointee som en anden pointer. Så efter opgaven, vil de 2 pejlemærker peger på samme pointee. Nogle gange kaldes deling. Og det er alt der er til det virkelig. Bye-bye nu. Dette er Binky. Det er CS50. Vi vil se dig i næste uge. [Bifald] [CS50.TV]