[Powered by Google Translate] [Uke 4, Fortsatt]
[David J. Malan - Harvard University]
[Dette er CS50. - CS50.TV]
>> Dette er CS50, og dette er slutten av uke 4.
Så noen gode nyheter og noen dårlige nyheter.
Ingen forelesning på mandag, setter ikke noe problem neste uke. [Studenter jubler]
Du kommer ikke til å like hvor dette går.
Men vi har dette i stedet neste onsdag,
og det er også i henhold til pensum en fredag ​​forelesning neste fredag, slik at vi kan holde deg på sporet.
Men alt vil bli filmet som vanlig, så ikke bekymre deg.
>> Og med hensyn til quiz 0 hva vi skal gjøre mot ukens slutt
er innlegg på kursets hjemmeside cs50.net en forklaring
av hva slags forventninger du bør ha når det kommer til den første quiz.
Generelt vil det være flere valg, true-false, korte svaret, korte koding problemer.
Du kommer ikke til å bli forventet å gjennomføre tilsvarende
av et problem som du ville se på en pset, som du har en datamaskin
og en debugger og lignende, men det vil være små koding problemer.
>> Og ja, den beste guiden for å få en følelse av hva CS50 spørrekonkurranser er som
er å gå til cs50.net, gå til Quizzes link,
og du kan se de siste årene verdt av spørrekonkurranser.
Bare innse at læreplanen ikke alltid har vært den samme gjennom årene.
Noen ganger kan vi legge til, noen ganger trekke fra,
så hvis du ser noen tema på en av de gamle spørrekonkurranser
at du ikke har noen anelse om hva det er snakk om, er det enten at vi dekker det
eller at vi ikke dekke det.
Men i form av anmeldelser, dette søndag, mandag og tirsdag
samt et kurs-wide gjennomgang økt på søndag kveld -
tid og sted vil bli annonsert på kurset hjemmeside -
dere alle har en mulighet til å gjennomgå med kursets undervisning stipendiater
materialet for dette året, både i snitt og som en full klasse,
og de vil bli filmet som vanlig også.
>> OK. Så uten videre, én kommentar bestått / ikke bestått og legg til / slipp.
Du har kanskje sett mine notater i går kveld, og dette er egentlig bare litt ekstra oppmuntring
at hvis du er blant de spesielt mindre komfortable eller et sted i mellom
og du føler deg bare litt over hodet,
skjønner det er faktisk ganske vanlig, og det er en god støtte strukturen på plass,
hvorav kontortid var innstilt på å forbedre alle mer per e-posten min i går kveld,
og innser også at et alternativ som bestått / ikke bestått for en klasse som dette
virkelig er ment som en mekanisme for å ta kanten av av et kurs som dette,
slik at nytt hvis du tilbringer de 10, 15, 20 timer
prøver bare å få litt pset å jobbe og du vet at du 90-95% av veien dit
men du kan ikke finne noen jævla bug, i en bestått / ikke bestått modell som er liksom greit.
>> Tanken er at med den mekanismen kan du deretter gå fokus på de andre psets
eller sove eller hva det er som du ønsker å fokusere på.
Så skjønner at du har inntil førstkommende tirsdag - teknisk 5. mandag,
men det er en ferie, så førstkommende tirsdag - for å bytte fra bestått / ikke bestått til gradert eller vice versa.
Og hvis du er virkelig på stupet og tenker på å slippe helt,
vennligst ta meg etter foredraget eller send meg en melding.
Vi vil gjerne minst chat før du legger inn bud adjø.
OK. Så vi begynte å ta trening hjul av forrige gang.
Spesielt har vi fokusert på streng.
String er noe som deklarert i CS50 biblioteket,
spesielt i den filen som heter cs50.h som vi vil begynne å se på denne uken og neste.
Men strengen er egentlig bare en forenkling av noe
som er litt mer arcanely beskrevet som char *.
Char vi er kjent med. Det er bare ett tegn.
Men * fra mandag betegnet hva? >> [Student] En peker.
En peker. Og hva er en peker? >> [Student] En adresse.
>> Det er som en adresse, et sted i minnet.
Hva er en adresse eller et sted eller minne?
Igjen, alle av oss har bærbare datamaskiner med en gig eller to gigabyte RAM mest sannsynlig i disse dager,
og det betyr at du har en milliard eller 2 milliarder bytes verdt minne.
Og det spiller ingen rolle egentlig hva det fysisk ser ut,
men ta på tro at du kan telle alle de individuelle byte som din egen laptop har -
Dette er byte 0, er det byte 1, dette er byte 2 milliarder -
og det er akkurat hva en datamaskin gjør.
Når du tildele plass for en enkelt karakter, for eksempel,
det har åpenbart å leve et sted i datamaskinens minne,
og kanskje det er på byte nummer 12345,
og det er et sted her oppe i datamaskinens minne.
Og adressen da av at karakteren er 12345.
>> Nå i uke 0 til nå, så langt har vi ikke egentlig brydde
hvor i minnet ting lagres fordi vi vanligvis bruker symboler,
variabler, og arrays å faktisk få på våre data.
Men som av mandag og alle de mer i dag, nå er du nødt til
alle de mer uttrykksfulle evner med å skrive programmer
å virkelig manipulere datamaskinens minne slik du ønsker,
for både gode formål og dårlige,
bugs er en svært vanlig resultat på dette punktet i å lære disse tingene.
Men hva betyr det egentlig å være en char *?
La oss gå videre tilbake til - og vi vil komme tilbake til Binky som lovet i dag.
La oss gå til et enkelt eksempel her.
La meg lagre denne filen som compare.c, og la meg bare få litt malkoder her
så ta stdio.h, la meg også gi meg selv inkluderer cs50.h. Jeg zoome inn der oppe.
La meg begynne å skrive viktigste int, main (void), og nå ønsker jeg å gjøre noe som dette:
printf ("Gi meg en streng:") og da vil jeg bruke streng s blir GetString
å få en streng fra brukeren, så jeg kommer til å be brukeren om en annen.
("Gi meg en annen streng:") og jeg kommer til å be dem via GetString å få det.
Jeg vil kalle det t fordi t kommer etter s og s er et fint navn for en streng hvis det er ganske generisk.
Så GetString, og nå er jeg bare ønsker å gjøre en mental helse sjekk, og jeg kommer til å si
if (s == t) da jeg bare kommer til å fortelle brukeren printf ("Du skrev det samme \ n");
ellers skal jeg skrive ut noe sånt ("Du skrev noe annet! \ n")
eller hva setningen vil bli. Så noe sånt.
Så som vanlig, vil jeg returnere 0 som bare betydde at ingenting dårlig skjedde,
og jeg kommer til å gå videre og kompilere og kjøre dette programmet.
>> Men på mandag kjørte vi dette programmet,
og faktisk ble fortalt at HELLO er ikke hei og farvel er ikke farvel.
Oppførselen vi så var litt mer som dette.
La meg gå inn i min kilde katalog, zoome inn her, og la oss gjør sammenligne.
Utarbeidet greit. La meg kjøre sammenligne. Gi meg en streng: HELLO.
Gi meg en annen streng: HELLO.
Du har skrevet inn noe annet!
Vel, la meg prøve noe enklere som 50, 50. Du har skrevet inn noe annet!
hei, hei. Så klart, er noe som skjer her.
Men hva var forklaringen på hvorfor?
Angivelig, er linje 12 helt dysfunksjonelle.
Hva er det grunnleggende problemet her? Ja. >> [Student] Det sammenligne adressene.
Ja, akkurat. Det er faktisk sammenligne adressene
hvor HELLO og HELLO er lagret.
Det er ikke sammenligne bokstavene HELLO igjen og igjen,
fordi hva som egentlig skjedde, hele denne tiden vi har brukt GetString -
Dette tavle er igjen vår datamaskinens minne,
og la oss si jeg kaller GetString etter å ha erklært en variabel s.
Hvordan ser min hukommelse ut?
La oss vilkårlig si at s ser slik ut. Det er en firkant.
Og ganske mye hver gang jeg har trukket et stykke minne på skjermen
hvis det er 32 biter jeg har vært å tegne firkanter som dette fordi faktisk i apparatet,
en peker, en adresse, er 32 bits. Det er det samme som en int.
Som kan variere basert på datasystemet.
De av dere som er litt kjent med det faktum at Mac-en eller PC er 64 bits,
som betegner faktisk at datamaskinen bruker 64-bits pekere,
64-bits adresser, og blant de upsides av det er datamaskinene
kan ha mye mer RAM enn yesteryear.
Lang historie kort, tilbake i dag da datamaskiner bare brukt 32 bits
å representere adresser, det største antallet byte du kunne representere
i så fall var det om du har 32 bits?
Så 4 milliarder kroner, høyre, fordi 2 til 32 er 4 milliarder.
Dette nummeret har blitt gjentakende i kurset.
>> Så hvis du bare har 32 bits, det høyeste tallet du kan telle til er omtrent 4 milliarder kroner.
Men det var en fundamental begrensning av datamaskiner inntil for få år siden
fordi hvis du bare kan telle så høyt som 4 milliarder kroner,
det spiller ingen rolle om du kjøper 8 gigabyte RAM eller 5 gigabyte RAM;
du kan ikke telle så høy, så det var ubrukelig.
Du kan bare få tilgang til første 3 eller 4 gigabyte datamaskinens minne.
Det er mindre av et problem nå, og du kan kjøpe MacBook Pro og Dells
med 8 gigabyte RAM eller mer i disse dager.
Men hvis jeg fordele ganske enkelt i dette programmet en peker, kalt en peker s,
det kan se slik ut på skjermen fordi faktisk vi trenger å skrelle tilbake dette laget.
Jeg fortsetter å si streng, men fra mandag er streng virkelig char *,
adressen noen tegn.
Så la oss ta det trening hjulet av, selv om vi vil fortsette å bruke GetString for nå.
Så jeg har erklært s, og dette er en del av minnet, 32 biter.
Hva finnes her i minnet som standard? >> [Uhørlig student respons]
Hva er det? >> [Student] Garbage. >> Garbage. Akkurat.
Hvis du programmerer ikke sette en verdi i en variabel, hvem vet hva det er?
Noen ganger får du heldig, og det er 0, som er slags en fin, ren standard verdi,
men som vi så mandag, noen ganger er det fullstendig meningsløst,
noen virkelig stor positiv eller negativt tall som kom fra hvor?
Ja. >> [Student] Funksjonen før. >> Ja.
>> Ofte den funksjonen som ble kalt før, fordi husk,
som du kaller funksjoner i minnet, de tar opp mer og mer plass fra bunnen opp,
og så snart funksjonen returnerer, blir det minnet om igjen
ved neste mann som blir kalt, er som bruker samme stykke minne.
Og hvis du har forlatt søppel der, tidligere verdier,
vi kan forveksle s som å ha noen verdi når vi virkelig ikke har satt noe der.
Så vår RAM på dette punktet ser slik ut.
Nå på høyre side av linje 7 vi kaller GetString,
som vi har gjort nå i flere uker, men hva er GetString egentlig gjør?
GetString skrevet av CS50 ansatte er litt intelligent
i at så snart brukeren begynner å skrive nøkler og treff Enter,
GetString tall ut hvor mange tastetrykk gjorde brukeren hit,
hvor mange tegn trenger jeg for å fordele RAM for.
Og hvor det RAM kommer fra, hvem vet?
Det er et sted i datamaskinens 2 gigabyte eller whatnot minne.
Men la oss anta at datamaskinen funnet plass for ordet HELLO her.
Ordet jeg skrev var H-E-L-L-O.
Og hvis vi trekke dette som en sekvens av tegn, kan vi trekke det ut som dette.
Men jeg trenger å gjøre en ekstra ting. Hva hører på slutten av noen streng i C?
Null karakter, som vi skriver som \ 0.
Det er teknisk tallet 0, men backslash gjør alt klarere
at dette er bokstavelig talt tallet 0, heltallet 0;
Det er ikke for eksempel, sitat-unquote 0 som du kan skrive på tastaturet.
Så dette er HELLO.
>> Og hva gjorde vi sier mandag at en funksjon som GetString
er faktisk returnere alle disse ukene?
Det er ikke returnere en streng per se fordi det ikke egentlig ha betydning
fordi strenger ikke eksisterer. De er liksom en fabrikasjon i CS50 biblioteket.
Hva er egentlig en streng, mer teknisk? >> [Student] Det er det første tegnet.
Akkurat. Det er rett og slett adressen til den første tegnet på at brukeren har skrevet inn
Så hvis mitt ord HELLO ender det opp på bytenummer 123 og deretter ved byte nummer 124,
125, 126, og så videre, hvis jeg bare mitt nummer bytes fra 0 på opp,
hva som virkelig GetString er tilbake er bokstavelig talt antall 123.
Så hva blir satt i s er antall 123, ikke bokstaven H, ikke ordet HALLO,
ganske enkelt hvilken adresse jeg kan finne den første bokstaven i HELLO.
Men det ser ikke ut som nok. Jeg spurte deg om en streng, ikke et tegn.
Så hvordan vet vi eller datamaskinen gjør at Ello slags kommer sammen med H?
Hva er slags enighet vi har? Ja.
[Student] Det holder å fortelle seg selv å finne noen flere tegn. >> Nettopp.
>> Det er denne menneske-maskin konvensjonen der når du arbeider med strenger,
ellers kjent nå som røye stjerner, du bare nødt til å finne ut
hvor på slutten av hver streng i livet er å egentlig bare gjentar over den med en for løkke,
en stund loop, uansett, slik at når du finner på slutten av strengen
nå kan du slutte fra det, oh, var hele ordet HELLO.
De av dere med tidligere erfaring med programmering kan vite i Java
du kan bare ringe. lengde og i andre språk kan du ringe lengde eller lignende.
Det er fordi i en rekke språk, spesielt ting som kalles objektorienterte språk,
lengden på noe er slags innkapslet inne i stykke data selv,
mye som vi innkapslet IDer og navn og hus inne i en student på mandag.
Men C er mye lavere nivå. Det er ingen objekter eller klasser, hvis du har hørt disse ordene før.
Alt du trenger er egentlig minne adresser.
Så dette er liksom den gammeldagse måten å representere interessante datastrukturer.
Du har en startverdi for eksempel adressen til det første tegnet
og deretter bare noen vilkårlige konvensjonen som alle er enige å følge.
Så hvordan er streng lengde implementert, vi foreslår?
Strlen, strlen, som noen av dere har nå brukt et par ganger. Det er ganske enkelt, ikke sant?
Det er som to linjer med kode.
Det er ganske mye en for løkke av noe slag, kanskje med en ekstra lokal variabel.
Men strlen har bare å ta en peker og deretter begynne å lete etter \ 0.
>> Og så snart den finner det, kan den returnere det totale antall skritt som det er tatt i strengen.
Så vi kan slutte fra dette hva som foregår på neste.
Anta så jeg erklærer t som jeg har gjort i linje 10.
Dette er noen søppel verdi. Hvem vet på først?
Men på høyre side av linjen på 10 jeg ringer GetString igjen.
Hvem vet hvor dette ender opp?
La oss vilkårlig si at operativsystemet funnet rom for det veien hit.
Jeg tilfeldigvis coincidentally type H-E-L-L-O igjen,
og slik at vi kan trekke samme type bilde.
Men det faktum at jeg har tegnet på nytt dette bildet er bevisst
fordi det er en annen HELLO enn dette.
Så her dette kan være plasseringen 456, dette er 457, og så videre.
Så hva blir satt der spørsmålstegn gang var?
I dette tilfellet 456.
Vi plukker disse tallene vilkårlig fordi egentlig etter dag
Vi kommer ikke til å bry seg så mye om hva adressen alt er.
Alt vi bryr oss om er at vi kan finne ut adressen til noen del av data som HELLO.
>> Så egentlig hva folk flest gjør i informatikk når vi snakker om minneadresser
og snakker om pekere spesielt,
snarere enn bry å finne ut 123 - hvem bryr seg hvor dette ting faktisk er,
Vi bare vet at det er på noen numerisk adresse -
vi forenkle verden og bare si at s peker til det tegnet
og t peker til det tegnet.
Og det faktum at det er en pil er ganske tilsiktet
fordi bokstavelig talt nå s peker på H og t peker på den andre H
fordi på slutten av dagen, spiller det ingen rolle hva adressen er,
men det spiller ingen rolle at vi har evnen til å uttrykke denne adressen med noen del av koden.
Vi har egentlig ikke manipulert disse adressene ennå
så vi får se hvor vi kan skyte og liksom gjøre ting med pekere,
men for nå i linje 12 bokstavelig talt hvilke verdier vi sammenligner
ifølge denne historien på linje 12?
Vi sier er 123 lik lik 456? Og det er definitivt ikke tilfelle.
Og selv konseptuelt, er denne pekeren definitivt ikke det samme som dette
fordi du ringte GetString to ganger, og GetString prøver ikke å være super flink,
det prøver ikke å innse, oh, skrev du HELLO 5 minutter siden;
la meg gi deg den samme pekeren som jeg ga deg før,
den fordeler bare en ny del av minnet hver gang du kaller det.
>> Så hvordan løser vi dette problemet?
Hvis høyere nivå jeg vil sammenligne strengene Hei og hallo -
Jeg bryr meg ikke om pekere - hvordan går jeg om å svare på spørsmålet,
gjorde brukeren skriver det samme? Det som er nødvendig her? Ja.
[Student] Bruk en funksjon. >> Jeg kan bruke en funksjon ut av boksen.
Jeg kan bruke en funksjon kalt strcmp, s-t-r-c-m-p,
bare en forkortet versjon av si streng sammenligne.
Og hvis vi går inn, for eksempel sammenligne 2, som er blant dagens brosjyrer,
Jeg gjør akkurat det.
Jeg holdt alt annet det samme fra linje 1 ned til 26 eller så,
og nå merker denne delen har endret bare litt.
La oss ignorere linje 28 for et øyeblikk og fokusere bare på denne.
Hva sa vi mandag at str Sammenligning gjør?
Den håndterer prosessen med å ta 2 pekere, S og T i dette tilfellet,
slags praktisk talt sette fingeren på de to bokstavene,
og hva det må gjøre er noe som en stund løkke eller en for loop,
og det sier er disse det samme? I så fall flyttes fingrene eller pekere fremover.
Er disse like, disse samme, disse samme,
disse samme, disse samme? Og ooh, jeg er på slutten av strengen både s og t.
Jeg har ikke funnet noen selvmotsigelser. Ja, disse strengene er de samme.
Og hva sammenligne str retur hvis to strenger er de samme, tilsynelatende? Zero.
Så 0 er god i dette tilfellet fordi hvis det returnerer -1 eller +1,
det betyr at s bare skjer for å komme før t alfabetisk eller etter t.
Og hvorfor skulle det være nyttig å ha en funksjon som forteller deg hvilke streng kommer før
eller etter i en ordbok?
[Student] Searching. >> Søke og sortering.
>> Så du kan gjøre ting som binære søk eller boble sortere eller flette slag
hvor du må sammenligne ting.
Så langt vi har slags kutte noen hjørner og bare snakket om sortering
i sammenheng med tall fordi det er hyggelig og lett å snakke om,
men du kan sikkert sammenligne strenger, eple og banan,
fordi hvis Apple er kjent for å komme før banan, på samme måte,
kan du flytte strenger rundt i minnet akkurat som Rob gjorde med fletting slags i videoen
og vi gjorde her på scenen med valg sortere, innsetting sortere og boble slag.
Så hvor ellers kan vi ta dette? La oss prøve dette.
La oss liksom glemme at leksjon for et øyeblikk og prøv nå og kopiere 1.c til å gjøre følgende.
I tråd 21 jeg sier print noe,
så jeg får en streng fra brukeren,
så jeg sjekker dette.
Vi har egentlig ikke kommet inn på denne vanen ennå, men la oss nå gjøre dette.
La oss faktisk skrelle tilbake dette laget. Dette er virkelig char *. Denne fyren er virkelig char *.
Så hva betyr det å være sjekker om s == NULL?
Det viser seg at når du ringer en funksjon som GetString
eller mer generelt bare spør en datamaskin for å gi deg noen minne,
noe kunne gå galt.
Du kan være gal, og be datamaskinen om en terabyte med minne
ved å be om billioner av byte som bare ikke eksisterer i datamaskinen,
men GetString og andre funksjoner trenger noen måte roping på deg
Hvis du har bedt om for mye.
Og måten GetString gjør dette er hvis du har bedt om mer minne
enn det som er tilgjengelig i datamaskinen, selv om det er super, super lav sannsynlighet
fordi ingen av oss kommer til å skrive en trillion tegn og trykk Enter,
men lav sannsynlighet selv om det kan være, jeg ønsker fortsatt å se etter det bare i tilfelle,
og den spesielle verdi som GetString, svar, og andre funksjoner avkastning
hvis noe har gått galt er NULL i alle caps.
>> Og hva er NULL? NULL bare så skjer for å representere en peker. Det er minneadresse 0.
Verden besluttet at vilkårlig, hvis dette er min datamaskinens minne - vet du hva? -
vi kommer til å stjele bare 1 byte av hver datamaskinens minne, og dette er stedet 0.
Vi kommer til å gi den et kallenavn av NULL, og vi kommer til å love
at vi aldri vil faktisk sette reelle data der
fordi vi bare vilkårlig trenger en spesiell verdi, 0, aka NULL,
slik at vi kan kjefte på brukere hvis noe går galt.
Ellers kan du kanskje ikke vet betyr 0 sette noe her
eller betyr det noe gikk galt?
Vi må alle enige om at NULL betyr ingenting ble returnert,
ingen faktiske adressen ble returnert.
Nå, her er jeg bare vedta mitt menneskelige konvensjon av jeg kommer tilbake en fra main
hvis noe går galt.
Det er fordi viktigste er tilbake konvensjonen er å returnere 0 hvis bra,
1 eller en annen verdi dersom dårlig.
Men GetString og alle funksjoner som avtaler i minne returnerer NULL hvis noe går dårlig.
>> Okay. Så dessverre, ikke 27 linje, super enkelt om det er helt å kopiere strengen.
Hvorfor? Vi kan se dette som følger.
Jeg vil hevde at i linje 27 som skal lage en kopi av s og kaller det ikke.
Så jeg ikke ber brukeren om to strenger denne gangen, jeg sier bare verdien i s
bør settes i t samt.
Så nå bare for å demonstrere hvor ødelagt dette er, i linje 29 og fremover hva jeg gjør?
Først skal jeg sjekke om lengden på t er større enn 0.
Det er noen streng der. Brukeren har skrevet noe i.
Hva er linje 32 gjør, tilsynelatende?
[Uhørlig student respons] >> Høyre. Du kan slags antyde det fra hva jeg sa det gjør.
Men teknisk sett, er hva dette gjør? t [0] representerer hva?
[Student] The zeroth karakter. >> [Malan] The zeroth karakter.
Eller, mer menneskelignende, det første tegnet i t, uansett hva det er, H kanskje i dette tilfellet.
Og toupper gjør hva den sier. Det drar fordel zeroth karakter t og det forandrer det.
Så dette betyr å ta zeroth karakter t, gjør det store bokstaver,
og sette den tilbake i samme sted.
Så hvis jeg skriver hei med små bokstaver, bør dette endre små h til en kapital H.
Men problemet er at i linjene 35 og 36 hva jeg skal gjøre er å skrive ut for oss s og t.
Og hva er din anelse?
Hva skal jeg faktisk kommer til å se om jeg har skrevet i hallo i alle små bokstaver?
Hva kommer til å få trykt? >> [Uhørlig student respons] >> Hva er det?
[Student] Big H og resten små. >> Den stor h og resten små som, s eller t?
[Student] Begge. >> Begge. Akkurat. Så la oss se hva som skjer her.
>> La meg gå videre og kompilere dette. Dette er Kopi1, så sørg Kopi1. OK.
Zoome i. La meg gå videre og kjøre Kopi1, Enter, Si noe: hello små bokstaver.
Det kapitalisert kopien, men det tilsynelatende aktivert den opprinnelige også,
fordi det som skjer nå i denne historien?
I linje 27 jeg ikke faktisk synes å være å kopiere strengen,
men selv om du kanskje har intuitivt håpet at å være tilfelle,
hvis du tenker på dette bildet, det som virkelig har jeg gjort?
Halvdel av bildet er den samme.
Så la oss rulle tilbake i tid, slik at t ikke eksisterer ennå i historien.
S kan eksistere i historien, men la oss små bokstaver hei denne gangen.
Så la meg fikse hva jeg faktisk skrev i.
I dette tilfellet har vi her h-e-l-l-o.
Vi vil trekke det som en sekvens av tegn, sette min separator linjer her og min \ 0.
Så dette er hvor vi er så snart linje 1 til og med 24-ish, gi eller ta, har gjennomført.
Dette er bildet av min hukommelse.
Når jeg kommer til linje 27, hva skjer?
Akkurat som før, får jeg en peker, som jeg vil trekke så denne plassen.
Det kalles t. Og hva er verdien som standard? Hvem vet? Noen søppel verdi.
>> Så jeg skal abstrakte at bort som et spørsmålstegn.
Og så snart høyre side av linje 27 kjører, hva jeg setter innsiden av t?
Det samme som er i s.
Så hvis vi for et øyeblikk fjerne denne abstraksjon av pilen, og vi sier,
oh, er dette minnet belastning adresse 123, når du sier t får s, semikolon,
du bokstavelig talt setter 123 her.
Hvis vi nå slags forenkle vår verden igjen med bilder,
hva du har virkelig gjort er nettopp lagt en pil til din verden
som er peker fra t til samme nøyaktige strengen.
Så når du er i tråd 31 og 32 faktisk jeg går om å endre t [0],
hva er t [0] tilsynelatende synonymt med nå? s [0]
Så det er alt som skjer.
Og selv om denne typen føles litt lavt nivå og uforståelige
og denne typen føles som kanskje intuitivt dette skulle ha bare jobbet -
Jeg har laget kopier av ting før, og det bare virket -
hvis du faktisk tenke på hva en streng egentlig er, er det en char *.
Vel, hva er det? Det er adressen til noen tegn.
Så kanskje det er mer fornuftig at når du prøver å gjøre noe
super tilsynelatende enkelt som dette, er alt du gjør kopiere et minne adresse.
Du er ikke faktisk gjør noe med selve strengen.
Så selv om du har ingen anelse om hvordan du ville løse dette problemet i koden,
høyt nivå, konseptuelt, hva vi trenger å gjøre for å gjøre ta tro kopi av s, tilsynelatende?
Ja. >> [Student] Gi den et nytt sted? >> Nettopp.
>> Vi trenger å gi t en splitter ny plassering.
Vi må liksom lage en verden der vi får en ny del av minnet,
som bare for klarhet skyld vil jeg trekke rett under dette, men det trenger ikke å være der.
Men det må være samme størrelse, så jeg vil trekke disse vertikale linjer på samme sted.
Det er greit hvis dette er alt søppel i utgangspunktet. Hvem vet hva som var der?
Men trinn 1 er nødt til å være gi meg så mye minne som jeg trenger
å passe en kopi av Hallo, deretter finne ut hvordan du kan kopiere h her, e her,
l her og så videre.
Men dette allerede skal føle litt opplagt selv om noen av detaljene er fortsatt abstrakt.
Å kopiere denne strengen i dette, det er bare en for løkke eller en stund loop
eller noe som du har blitt alt mer kjent.
Så la oss prøve dette. La meg gå inn copy2.c.
I copy2.c har vi nesten det samme programmet med unntak line 27.
Det ser litt komplisert, men hvis vi bryter det ned bit for bit,
den venstre side er den samme.
Char * t skaper denne tingen i minnet, om enn med et spørsmålstegn
fordi vi har ingen anelse om hva som er der som standard.
På høyre side er vi introduserer nå en ny funksjon, malloc,
for minne tildele, gi meg minne,
og det tar tydeligvis hvor mange argumenter, hvor mange ting inne i parenteser?
Jeg hørte knurr av 1 og 2, men det er bare en.
Det er ingen komma, som betyr at det er bare en ting i parentes.
Selv om det er andre parentes, la meg fremheve
hva er inne i de ytterste parentes, og det er dette uttrykket:
(Strlen (s) + 1) * sizeof (char).
Så hvis vi faktisk tenke gjennom dette, dette sier gi meg lengden på s.
Hvorfor er jeg, men legger en på lengden? >> [Uhørlig student respons]
Akkurat. Vi trenger plass for denne fyren på halen, den sjette tegnet som ikke har noen engelske betydningen
men har spesiell programmatisk betydning.
>> Så vi trenger en + 1 for at fordi strlen returnerer den menneskelige forventning om lengde,
Hei eller 5, vil det ikke gi deg den ekstra null karakter.
Så jeg manuelt legge dette med + 1.
Og så dette, * Størrelsen på (char), har vi ikke sett dette før.
Dette er ikke teknisk sett en funksjon.
Det er en spesiell søkeord som bare forteller deg hva størrelsen er av noen datatype på en datamaskin
fordi i virkeligheten, noen av oss har 32-bits datamaskiner.
Jeg har en ganske gammel datamaskin hjemme, og det bare bruker 32 bits til å representere pekere.
Og så hvis jeg gjorde størrelsen på en datatype, kan det være 32 biter.
Men hvis jeg bruker min nye fancy datamaskin, kan jeg få tilbake en verdi på 64 bits
for noe sånt som en adresse.
Så i dette tilfellet, bare for å være super trygg, vi kommer ikke til å hardkode noe sånt -
Vel, hva er på størrelse med en char henhold til hva vi har sagt så langt?
Vi har ganske mye sagt verbalt at det er en byte, og det er ganske mye sant over hele linja.
Men igjen, forutsetninger tendens til å være dårlig.
De fører til buggy programvare hvis folk bruker programvaren på måter du ikke har tenkt.
Så la oss abstrakt dette bort og bare mer generelt si
Jeg trenger dette mange biter av minne
og hver del av minnet skal tilsvare størrelsen på en karakter,
som faktisk er lik 1 i dette tilfellet, men det er en mer generisk måte å skrive det.
Så hvis ordet er hallo, ikke hvor mange byte malloc tilsynelatende tildele for hallo?
[Student] Six. >> Six. Akkurat så mange som vi har spørsmålstegn på skjermen.
Og deretter ta en gjetning nå basert på din forståelse av GetString
hva betyr malloc trolig tilbake? >> [Student] En adresse.
En adresse for hva? Av den første del av minnet.
>> Vi har ingen anelse om hva som er der fordi noen annen funksjon
kunne ha brukt dette minnet tidligere.
Men malloc, som GetString, returnerer adressen til den første byte minne
at det har satt for deg.
Men er å fylle hva det gjør ikke i denne blank med en backslash null tegn
fordi det viser seg at du kan bruke malloc å fordele noe: Ints, strenger, arrayer,
flyter, student strukturer.
Du kan bruke malloc helt generisk.
Det bryr seg ikke eller trenger å vite hva du tildele minne for.
Så det ville være arrogant for malloc å sette en \ 0
på slutten av hver del av minnet er det å gi deg
fordi dette \ 0 ting er bare en konvensjon for strenger.
Det er ikke brukt for ints, er det ikke brukt for flyter, er det ikke brukt for studenter.
Og så fikser med malloc er at belastningen er helt på deg programmerer
å huske hvor mange bytes du tildelt og ikke å stadig bruke en for loop
eller en stund loop og gå forbi grensen for mengde minne du har fått.
Sagt på en annen måte, så snart du allokere minne,
du kan ikke be operativsystemet, oh, forresten, hvor stor av en del av minnet var dette?
Det er helt opp til deg å huske om du trenger denne verdien.
>> Så la oss se hvordan jeg fortsette å bruke dette minnet.
I linje 28 og 29 hvorfor gjør jeg dette?
Bare total mental helse sjekk.
Bare i tilfelle noe gikk galt, ber jeg for noen sprø mengde minne
eller jeg har så mange ting kjører på datamaskinen som det er bare ikke nok minne,
noe sånt, jeg minst ønsker å sjekke for null.
I virkeligheten vil de fleste datamaskiner gi deg en illusjon om at hvert program
kan bruke sin helhet av RAM,
men selv så, hvis brukeren skriver i noen sprø lang streng kanskje fordi de er en dårlig fyr
og de er faktisk prøver å krasje programmet eller banalisere i det,
Vil du i det minste sjekke returverdien av malloc og om det er lik null.
Og hvis den gjør det, la oss bare slutte akkurat nå, fordi jeg ikke vet hva jeg skal gjøre i dette tilfellet.
Hvordan kopierer jeg strengen? Det er noen måter å gjøre dette på.
Det er str kopiere funksjoner i C, men det er super enkelt for oss å gjøre dette på den gammeldagse måten.
>> Først la meg finne ut hva lengden på s er.
Jeg kunne ha satt dette i loop, men i stedet jeg bare sette den ut her for klarhet.
So I lagrer nå lengden av den opprinnelige streng, som er tilsynelatende 5.
Så i min for loop jeg gjentar fra 0 på opptil n,
og på hver iterasjon jeg setter s [i] innsiden av t [i].
Så det er hva jeg antydet med mine 2 fingre peker på strengene før.
Ettersom dette for loop gjentar som dette, kommer jeg til å være kopiere h inn her,
e inn her, jeg inn her fordi dette er s, dette er t.
Og så til slutt, i tråd 35 hvorfor gjør jeg dette?
Jeg må sørge for at jeg slutter strengen t.
Og jeg gjorde det på denne måten å være super eksplisitt.
Men foreslå noen, hvis du kan, en annen måte å gjøre dette på.
Jeg vet egentlig ikke trenger linje 35. Det er en annen måte å gjøre dette.
Ja. >> [Uhørlig student respons] >> Si det høyere.
[Student] Mindre enn eller lik. >> Nettopp.
Vi kan bare si mindre enn eller lik n, som generelt har vært dårlig
fordi nesten alltid når vi går opp til en lik ting vi teller
vi går en skritt for langt.
Men husk, ikke hvor mange byte vi fordele?
Vi allokert strlen av s, så 5 + 1 for en total på 6.
Så i dette tilfellet kan vi gjøre noe som dette
slik at vi kopierer ikke bare hallo, men også \ 0 på slutten.
Alternativt kan vi bruke en funksjon kalt str kopi, strcpy,
men det ville ikke være nesten like mye moro.
Men det er alt den gjør under panseret.
Så til slutt, gjør vi det samme som før.
Jeg kapitalisere t og da jeg hevder at den opprinnelige ser ut som dette, og kopien ser sånn.
Så la oss prøve dette nå. La meg gå inn her. Gjør COPY2. Vi vil zoome inn og kjøre COPY2.
Jeg kommer til å skrive hei med små bokstaver, og faktisk jeg får små bokstaver Hei som den opprinnelige
men hovedstaden Hei for kopien.
Men jeg er ikke ferdig ennå. Jeg trenger å gjøre en siste ting her.
46 og 47 er klart frigjøre minne, men hva betyr det egentlig?
Hva gjør jeg, tror du, ved å kalle linje 46 og linje 47?
Hvilken effekt har det? Ja.
[Uhørlig student respons] >> Nettopp.
>> Du er bare å fortelle operativsystemet, hei, takk for dette minnet.
Du kan nå bruke den til noen andre.
Og her er et perfekt eksempel på søppel verdier.
Jeg har bare brukt dette minnet for å skrive ned ordet hallo i 2 steder,
her, her, her og her.
Så dette er h-e-l-l-o-\ 0.
Men da jeg kaller linje 46 og linje 47, og du vet hva som skjer der i form av bildet?
Egentlig, vent, dette bildet er den gamle.
Når vi gjør kopien, er denne fyren faktisk peker her,
så la oss ta tallene og bare abstrakt bort som våre pilene igjen.
Hva skjer i dette bildet når jeg ringer gratis?
[Uhørlig student respons] >> Ikke engang.
Hvis jeg ringer gratis på s og t - slags et lurespørsmål - dette bildet ikke endres i det hele tatt
fordi ringer s og ringer t forteller bare operativsystemet,
hei, kan du bruke dette minnet igjen, men det endrer ikke dette til null
eller noen spesiell karakter, betyr det ikke endrer dette,
det endrer ikke h eller e eller l eller l eller o i enten sted til noe annet.
I form av bildet, så snart du ringe gratis, ingenting endres.
Og der ligger opprinnelsen av søppel verdier fordi hvis jeg senere i dette programmet
spør operativsystemet for mer minne med GetString eller malloc eller noe sånt
og operativsystemet sier at, jeg har 12 byte minne bare frigjort,
bruke disse, hva er det du kommer til å bli levert?
Du kommer til å bli levert en del av minnet som vi vanligvis ville trekke
med spørsmålstegn, men hva er de spørsmålstegn?
De måtte være H-e-l-l-o, H-e-l-l-o.
Dette er våre nye søppel verdier så snart du frigjøre dette minnet.
>> Det er en virkelig verden implikasjon her også.
Dette skjer for å gjøre med RAM, men datamaskinene
faktisk gjør det samme med disken.
Vi skal snakke om dette i særlig med et fremtidig problem sett som fokuserer på etterforskning.
Men hva skjer egentlig hvis du har noen sensitive økonomiske filen på skrivebordet
eller noen sketchy JPEG og du drar det inn papirkurven,
hva skjer når du drar den i papirkurven eller papirkurven?
Du visste hva jeg snakket om. [Latter]
Hva skjer når du har dratt at bevis i papirkurven eller papirkurven kan?
[Uhørlig student respons]
Vel, så forsiktig. Hva skjer når du gjør det?
Det korte svaret er ingenting, ikke sant?
Sketchy eller sensitive filen fremdeles bare sitte der et sted på harddisken din.
De fleste av oss minst har lært på den harde måten at du trenger å tømme papirkurven
eller papirkurven å faktisk slette filer.
Og ja, når du høyreklikker eller Kontroll-klikk på papirkurven kan
eller velg Fil, Tøm papirkurv eller hva
og du faktisk tømme papirkurven kan eller papirkurven, hva som faktisk skjer deretter til dette bildet?
Mer ingenting. Slik at ingenting skjer faktisk på disk.
>> Og hvis vi bare midlertidig digress og skrive - Jeg skal bare bruke baksiden av dette.
Så nå historien endrer seg fra RAM, som er der programmer eksisterer
mens du kjører dem, til disk, som er der de er lagret langsiktig
selv når strømmen går ut, for nå - og vi vil komme tilbake til dette i fremtiden -
la oss bare late som om dette representerer harddisken i datamaskinen din
fordi tilbake i dag pleide de å være sirkulære disker, mye som disketter.
Så hvis du har noen sensitive Excel-fil, kan det ta opp denne del av minnet
på datamaskinens disk, og jeg bare tegne samme vilkårlig 1s og 0s.
Når du drar filen sånn til papirkurven kan eller papirkurven,
bokstavelig talt ingenting skjer fordi Apple og Microsoft har nettopp besluttet
papirkurven kan og papirkurven er egentlig bare en midlertidig plassholder.
Kanskje slutt OS vil tømme den for deg, men vanligvis er det ikke gjør noe,
minst til du er veldig lav på plass.
>> Men når du går til Tøm papirkurv eller tom papirkurven,
på samme måte, skjer det ingenting av dette bildet.
Alt som skjer er et annet sted på datamaskinen, er det en slags bord.
Det er liksom som en liten jukselapp som sier det, la oss si, resume.doc,
så din CV i et Microsoft Word-fil som brukes til å leve på stedet 123 på harddisken,
ikke i minnet og ikke i RAM, men på harddisken,
og dine sketchy JPEG liv i 456, og Excel-filen bor på 789 eller der.
Når du sletter filer ved å faktisk tømme papirkurven eller papirkurven,
Dette bildet endrer seg ikke. Den 0'er og 1'ere på harddisken ikke gå hvor som helst.
Men denne tabellen, denne lille database av former, gjør endringen.
Når du sletter din CV, er det som om filen er slettet i en viss forstand,
men alle Datamaskinen glemme er der at ting lever på harddisken.
Den 0'er og 1'ere som komponerer din CV eller noen av disse andre filer er fortsatt intakt.
>> Så hvis du gjorde dette ved et uhell, det er fortsatt en ikke-null sannsynlighet
at du kan gjenopprette data med Norton Utilities eller noen kommersiell programvare
hvis formål i livet er å finne 0'er og 1'ere som har liksom blitt foreldreløse,
glemt her, men igjen her, slik at du kan få dataene tilbake.
Eller rettsmedisinske etterforskere med politiet eller FBI ville faktisk ta en harddisk
og faktisk se etter mønstre av 0'er og 1'ere som ser ut som JPEG, ser ut som Excel-filer,
og gjenopprette dem på den måten selv om datamaskinen har glemt dem der.
Så den eneste måten virkelig å slette data, som vi vil diskutere i fremtiden,
er å skrubbe eller tørk filen eller harddisken ved -
Du kan egentlig ikke bli kvitt den 0'er og 1'ere
fordi ellers du ville starte med en gigabyte harddisk
og du vil ende opp med en megabyte harddisk hvis du stadig var å slette,
bokstavelig talt, 0'er og 1'ere.
Så hva ville du gjøre hvis du virkelig ønsket å dekke dine spor
og det grunnleggende problemet er at det fortsatt er 0'er og 1'ere på disken?
Jeg ser noen gestikulerer at du ville fysisk bryte enheten. Som vil fungere.
[Latter] Men hvis det er slags en kostbar løsning, hva ville være mer fornuftig?
Ja. >> [Student] Overskriv dem. >> Overskrive dem med hva? >> [Student] Andre data.
Andre data. Du kan bare overskrive disken med 0s eller 1s eller alle 0s, alt 1s.
>> Og det er faktisk hva noen av programvaren gjør.
Du kan kjøpe programvare eller selv få fri programvare,
og selv innebygd i Mac OS disse dager, mindre i Windows,
er evnen til å sikkert slette.
Egentlig, hvis du ønsker å alle kjøre hjem i dag hvis du har en Mac og gjøre dette,
hvis du har noen ting i papirkurven kan, kan du gjøre Sikker tømming,
som gjør akkurat det.
Snarere enn bare slette filer her, betyr det ikke slette 0'er og 1'ere her,
heller, endrer det bare dem alle, for eksempel til 0'er og prikk, prikk, prikk.
Så en av dine fremtidige psets vil faktisk være å bevisst gjenopprette data -
bildene vi har tatt av folk, steder og ting på campus
som vi skal gjøre en rettsmedisinsk bilde av et digitalt kamera minnekort,
som er nøyaktig samme idé - og du må bli utfordret til å faktisk finne
mønstrene som representerer JPEG på harddisken,
mye som det tidligere student som e-post leste jeg for noen uker siden gjorde
å gjenopprette hans søster fotografier.
Hvorfor ikke vi ta en 5-minutters pause her, og vi vil omgruppere med mer på minne.
Så her er der ting blir litt mind-bending, men dette er en svært kraftig skritt
mot å forstå dette enda mer.
Her er et program som heter pointers.c.
Det er blant dagens eksempelkode.
Legg merke til at i de første linjene, 19 til 22, er alt vi gjør noe sånt GetString
og returnere en adresse, lagre den i s.
Heretter for pset selv 3 hvis du vil, men pset 4 og på
hvor du kan begynne å ta disse trening hjul utenfor deg selv,
det er ingen grunn til å late som strenger eksisterer lenger.
Det er sikkert greit å bare begynne å si char *.
>> Som en side, i online referanser og i bøker kan du ofte se stjernen ved siden av variabelen.
Du kan selv se områder rundt begge sider av den.
Alle disse er funksjonelt riktig.
For nå, men vil vi standardisere på denne tilnærmingen til å gjøre super klart
at char * er som å si karakter pekeren.
Det er datatypen.
Og så navnet på variabelen er s i dette tilfellet.
Så vi har fått en streng og vi har kalt det er.
Og deretter ned her legge merke til at jeg gjør faktisk litt lureri.
Dette kalles pekeren aritmetikk, som er slags super enkelt.
Det betyr bare legge til og trekke fra tall til pekere.
Men dette fungerer faktisk.
Dette programmet skriver tilsynelatende strengen s 1 tegn per linje slik at sluttresultatet -
Så vi kan ødelegge hvor dette går, gjør pekere, kjøre pekere, la meg zoome inn
Nå la meg skriver noe sånt HELLO og type Enter
og det skrives en tegn per linje.
Opp til en ny siden, ville vi ha gjort dette med hakeparentes notasjon.
Vi ville ha en for loop og vi vil gjøre printf av s [i], og vi vil gjøre det igjen og igjen og igjen
med en omvendt skråstrek n ved enden av hver linje.
Men dette programmet er annerledes. Dette programmet bruker, bokstavelig talt, aritmetikk.
Så hva er det som skjer her?
Først av alt, før denne sløyfen selv utfører, hva, bare for å være klar, er s egentlig?
S er? >> [Student] En adresse. >> En adresse.
>> Og det er adressen, i tilfelle av hei, det første tegnet i det ordet, er som h.
Så s er, i dette spesielle eksempel, adressen h.
Så hva betyr det å gjøre s + jeg?
Vel, begynner jeg på 0 i dette for loop. Vi har gjort det mange ganger.
I er kommer til å gå opp til lengden av strengen, tilsynelatende.
Så på den første iterasjon av denne sløyfen, i er åpenbart 0.
Så dette uttrykket sier s + i - snarere s +0--det er åpenbart bare er.
Så hva er * s her?
Nå vi bruker stjernen i en litt annen måte.
La meg gå videre og bli kvitt t fordi vi er ferdige å snakke om t og kopier av s.
Nå er vi bare ønsker å fortelle en historie som involverer s.
Og så i dette øyeblikk, etter å ha typen streng, ser vår verden helt som det gjorde før
med bare s lagring adressen h og mer generelt peker på strengen hallo.
Hvis jeg nå gjøre en linje som * (s + i), la oss prøve dette ut.
Så * (r + i). La meg forenkle dette fordi dette er 0, så dette er * (s +0).
Vel, vent litt. Forenkle videre. Dette er * (s).
Vel, nå parentes slags dum, så nå la oss bare gjøre * s.
Så i første iterasjon av denne sløyfen, den linjen som er uthevet, 26,
er ganske mye tilsvarer skriver dette.
Hva er datatypen for * s?
I denne sammenheng, fordi stjernen tilfeldigvis være ved siden s selv,
men mer spesifikt, fordi vi ikke lenger erklære s,
vi ikke lage en variabel lenger, det er ingen omtale av char * i linje 26,
det er ingen omtale av søkeordet streng, er vi bare bruker en variabel kalt s,
det viser seg nå stjernen har litt annerledes og riktignok forvirrende mening.
* S her betyr å gå til adressen i s og print alt som er der.
Så s er her, er * s - liksom som Chutes og stiger, følger pilen - her.
Så dette er * s.
>> Så hva blir trykket på første iterasjon av at loop i linje 26?
Jeg skriver ut% c, som er plassholder for en karakter,
deretter en \ n for en ny linje. * (S + i) hvor jeg er 0 er nettopp dette.
Så hva røye plasserer jeg i for% c? H.
I neste iterasjon av loopen - du kan sikkert se hvor dette går -
neste iterasjon jeg er åpenbart en, så betyr dette s en,
og så nå jeg trenger parentesene fordi nå stjernen må si
gå til minneadresse s +1.
Hva er s? La oss rulle tilbake i tid og si denne pilen nå ikke faktisk gjør oss noen tjenester.
La oss mer spesifikt si at dette er lagring av nummer 123
fordi begynnelsen av denne strengen hei, er denne adressen 123, dette er 124, og så videre.
Så på den andre iterasjon når jeg sier s +1, er at som å si 123 1,
ellers kjent som 124, så hva røye blir trykt på den andre iterasjon?
E på minneadresse 124.
Så + igjen, 125, 126, 127, og denne sløyfen stopper heldigvis før vi får her
fordi jeg bruker strlen å sørge for at jeg ikke teller for høy.
Slik som er for det.
Igjen, dette er akkurat som om vi hadde gjort for en uke siden.
La meg skrive det på linjen under selv om vi ikke ønsker å gjøre begge deler.
Dette er identisk nå til denne.
>> Så selv om s er en streng, som vi har vært ringer det i ukevis, er er virkelig en char *.
Så hvis vi ønsker å være super anal, det er virkelig riktig å skrive den spesifikke karakter
på ITH plassering ved hjelp av disse numeriske adresser og denne stjernen operatør,
men ærlig, dette er bare så mye renere. Så dette er ikke dårlig.
Ingen grunn til å slutte å gjøre linje 27 her, men 26 er funksjonelt det samme,
og det er funksjonelt det samme for nøyaktig grunnene til at vi har diskutert så langt.
Og til slutt, er 29 bare god praksis.
Ringe gratis s betyr at du nå er å gi tilbake minnet om at GetString ga deg
fordi igjen, som jeg nevnte mandag, GetString uker
har vært innføre en bug i koden din.
Koden for uker har hatt minnelekkasjer
der du har stilt GetString for minne, men du har aldri vært å gi den tilbake.
Og det var bevisst valgt av oss pedagogisk
fordi det er bare for mye å tenke på tidlig.
Men nå trenger vi mer symmetri.
Hvis du spør maskinen for minne, slik tilfellet er for GetString,
slik tilfellet er tilsynelatende for malloc,
Du må nå for pset 4 videre også gratis slike minne.
Merke dette er forskjellig fra å si int n.
Du trenger ikke å frigjøre dette fordi du ikke ringer GetString
og du ikke ringe malloc.
>> Og selv om du ringte GetInt som vi vil til slutt se,
GetInt Tildeler ikke minne for deg fordi du kan faktisk sende rundt heltall
og flyter og chars akkurat slik vi har gjort i flere uker.
Strenger, men er spesielle fordi de virkelig er den sammensetning av flere tegn.
Så de er bare annerledes fra chars og flyter og Ints og lignende.
Men vi vil komme tilbake til det før lenge.
Eventuelle spørsmål så på denne begynnelsen av pekere? Ja.
[Uhørlig student spørsmål]
Ah, veldig godt spørsmål.
En av de få tingene C faktisk gjør for deg, som er praktisk,
er det tall ut for deg hva størrelsen er av datatypen
og gjør deretter den slags multiplikasjon for deg.
Dette er irrelevant når det gjelder tegn fordi nesten alltid en røye er en byte,
så dette bare virker.
Men på grunn av diskusjonen, hvis du var faktisk skrive heltall
og du prøvde å skrive ut noen verdi s som pekte mot et heltall,
du på samme måte ikke trenger å gjøre + 4 * jeg bare fordi en int er 4 byte.
Pointer aritmetiske betyr at C og kompilatoren gjøre alt som regnestykket for deg.
Alt du trenger å bry seg om er opptelling i form av den menneskelige fornuft. Ja.
[Student] Hvis du erklære en streng inne i en for loop, har du å frigjøre det senere?
Godt spørsmål.
>> Hvis du erklært en streng inne i for loop, trenger du å frigjøre det senere?
Du trenger bare å frigjøre minne som du tildeler med GetString eller med malloc.
Så hvis du bare si noe sånt - la meg sette klammeparentes nå så all koden er relatert til.
Hvis du gjorde noe, om enn buggily, som dette, char * t = s,
du trenger ikke å gratis t fordi t ikke innebar noen omtale av malloc eller GetString.
Hvis derimot du gjorde dette, GetString, så ja, ville du trenger å gratis t.
Og faktisk, er din eneste sjanse til å gjøre det nå inne i denne sløyfen, for samme utgave av omfang
at vi har diskutert i det siste.
Ellers ville du være tildele minne, tildele minne, tildele minne,
og på slutten av programmet fordi du er utenfor som loop,
t eksisterer ikke, men du har aldri fortalt operativsystemet
at du ikke trenger det minnet lenger.
Og før lang, for pset 4 eller 5 vil vi utstyre deg med et program som heter Valgrind,
som er lik i ånden til GDB i at det har litt av en uforståelige grensesnitt,
men dens formål i livet er å hjelpe deg.
Og Valgrind er et program som vil i fremtiden søke i programmene
på jakt etter minnelekkasjer, enten fra GetString eller malloc,
som vi vil ta i bruk alle de mer som vi slutter å bruke CS50 bibliotek så mye.
Vi endelig har nå liksom den ordforråd og den slags mental modell i teorien
som å løse denne brutt program.
>> Så i denne brutt program, fungerer swap innsiden av swap,
men det har aldri egentlig jobbet i hoved fordi main vedtatt i x og y, husker,
og de ble vedtatt i av verdier, så å si.
Kopier av dem ble gitt til bytte.
Ved utgangen av swap, hadde a og b faktisk blitt utvekslet,
men selvfølgelig x og y, som vi diskuterte mandag, ikke hadde vært.
Så jeg foreslår i grønt her at dette er faktisk den løsningen her.
Og faktisk, la meg flytte mine stjerner bare for å være konsekvent
selv om, igjen, funksjonelt dette spiller ingen rolle.
I fremtiden uker vil vi forklare når og hvorfor det gjør saken.
Så i grønt er nå en løsning.
Oppriktig, det ser en hel masse messier fordi jeg har alle disse stjernene.
La meg påpeke en ting.
Den øverste linjen her der det står int * a og int * b
er fundamentalt gjør det samme som det alltid har gjort.
Det er erklære 2 argumenter eller parametere for å bytte,
hvorav den første er en int pekeren kalles,
den andre av dem er et int pekeren kalt B.
Det eneste som er nytt på dette punktet er det faktum at det er en stjerne der.
>> Hva betyr det? A er ikke en int, er B ikke en int.
A er adressen til en int og b er adressen til en annen int.
Her nede, dette er hvor jeg innrømme C blir forvirrende.
Nå vi bruker en stjerne, men det har forskjellig betydning i denne sammenheng.
Fordi vi ikke erklære pekere som vi er her oppe,
her er vi dereferencing ting.
Så teknisk, stjernen i denne sammenheng av første, andre og tredje linje innsiden av swap
er å gå på dereferanse operatør, som bare betyr at det.
Så akkurat som min finger fulgte pilen til h,
* En del gå til denne adressen og finne meg int som er der.
* B del gå til adressen og passere meg hva som er der.
Så la oss tegne bildet fra mandag nå bruker en stabel av rammer,
den nederste av som kommer til å være viktigste,
den øvre av hvilke kommer til å være swap,
slik at vår verden ser ut, akkurat som mandag, som dette.
Her er en del av minnet som viktigste kommer til å bruke.
>> Husker fra mandag at programmet bare hadde 2 variabler,
en som heter X og en som heter y, og jeg hadde satt tallene 1 og 2 der.
Nå når jeg kaller bytte som jeg gjorde på mandag,
tidligere når jeg brukte den røde versjonen av dette programmet, som ser slik ut,
Jeg fikk 2 parametere, a og b, og hva gjorde vi skriver her og her?
Bare 1 og 2, bokstavelig kopier av x og y.
I dag har vi endre på det.
Dag i stedet for å sende i ints a og b vi kommer til å passere i to adresser.
Disse adressene skje til å peke på ints, men disse adressene er ikke Ints seg selv.
De er adresser. Det er som en postadresse i stedet.
Så nå må vi bare gi meg selv litt mer detalj på skjermen.
Dette er min datamaskinens minne som det har vært hele dagen.
Nå trenger vi noen vilkårlig nummerering ordningen.
Så la oss bare si, bare ved en tilfeldighet, at dette er minne adresse 123, 124.
La oss bare si dette er 125, er dette 126, og så videre, men det er helt tilfeldig.
Vi trenger bare litt nummereringen i min hukommelse.
Så nå når jeg faktisk passere i x og y, jeg kommer ikke til å passere i x og y;
Jeg kommer til å passere i postadresse, så å si, av x og y
slik at det som blir lagret her og her er ikke 1 og 2,
men hvis du kan se min lille tekst, blir det vedtatt i her og her?
[Uhørlig student respons] >> Nettopp. 123 blir satt her og 124 blir satt her.
>> Nå, fordi jeg brukte stjernen i denne aller første linjen helt opp her på toppen,
mitt program vet bare at 123 og 124, selv om de er åpenbart heltall
at ethvert menneske kunne merke, bør de tolkes som adresser, numeriske adresser.
De er ikke i og for seg ints, de adresser,
og det er fordi jeg har eksplisitt satt stjernene der.
Så nå i min første, andre og tredje linje av faktiske koden hva som skjer her?
La oss trekke resten av bildet.
Tmp er akkurat som det var på mandag. Ingenting spesielt med tmp.
Det er bare en lokal 32 bits variabel, og innsiden av det jeg tydeligvis lagring verdien av * en.
Nå, hvis jeg bare sa tmp = a, hva ville jeg satt her? >> [Student] 123.
123. Men det er ikke det jeg gjør.
Jeg sier tmp = * en. Stjerners del gå dit.
Så her er en, 123. Hvordan går jeg dit? Late som om det er en pil.
Vel, det er det, en. Så hva blir lagret i tmp, tilsynelatende? Bare 1.
Så med andre ord, er tmp * en, * en del gå til adressen som er i en,
som er tilsynelatende 123.
>> Ok, her er vi på stedet 123, ser jeg nummer 1,
så jeg kommer til å sette nummer 1 der.
Nå hva gjør jeg i linje 2, * a = * b?
Dette er en litt mer involvert fordi nå hva er en? Det er 123.
Så * a er der? Akkurat der jeg var før. Så gå dit. Okay.
Nå til slutt, og så til slutt vil begynne å gi mening, forhåpentligvis,
* B betyr hva som er i b? 124. Så jeg trenger å gå dit, som er 2.
Så hva setter jeg hvor?
2 går inn her fordi * b går inn * en. Så jeg skal gjøre det.
Og du kan allerede se, kanskje, at vi er så mye nærmere
å løse dette dumme, enkle problemet riktig for første gang
fordi nå har vi fortsatt en erindring av hva x var,
vi har 2 eksemplarer, riktignok av y,
men linje 3 sier nå * b.
Så her er b. * B betyr gå dit. Så hvor er plasseringen 124?
Det er tydeligvis her. Så hva setter jeg her? Selvfølgelig, tmp.
Så nå gjør jeg dette. Så jeg har en her og 2 her.
Og nå hva om alt dette, 123, den 124, og 1?
Så snart swap tilbake, er dette minnet så godt som tapt
fordi så snart swap avkastning, operativsystemet
er gratis å bruke dette minnet på nytt i fremtiden.
Bare main minne ved bunnen av denne såkalte stabel stikker rundt.
>> Og så skal vi endelig har nå en fungerende versjon.
La meg gå inn swap.c, og legge merke til følgende.
På toppen av programmet har jeg endret min prototype skal være int * a og int * b.
Så det eneste jeg endret til å gå fra rødt, som var dårlig, til grønn, noe som er bra,
er jeg lagt disse stjernene i dag.
Men så her nede i bytte selv jeg måtte kopiere, lime det var bare på lysbildet.
Jeg har en stjerne her, stjerne her - som samsvarer med prototypen -
og deretter alle disse tingene nå har stjerner bortsett tmp
fordi bruken av en midlertidig variabel, er det ikke noe nytt der.
Jeg trenger bare midlertidig lagringsplass for en int.
Så vi trenger ikke en stjerne der.
Vi trenger bare stjernen, slik at vi kan krysse denne typen vilkårlig grense
mellom disse to rammer i datamaskinens minne.
Men en siste ting må endres, og du kan ha skimtet det allerede.
Hva andre linjen er åpenbart annerledes nå? >> [Student] & x.
>> Ja, så 25 den siste linjen med kode jeg trenger å endre for at dette skal fungere.
For en uke siden, og selv på mandag linje 25 så ut som dette, bytte x og y,
og dette var bare brutt fordi hvis du sier swap (x, y)
du gir kopier av x og y å bytte, så det gjør sin ting,
men du aldri faktisk endrer x og y selv.
Så selv om du aldri har sett dette tegnet før med tegnet i koden,
bare ta en gjetning. Hva gjør tegnet, tilsynelatende?
[Student] Tar adressen. >> Tar adressen.
Så tegnet sier gi meg adressen til x.
Hvem vet hvor det er? Det skjer for å være 123. Jeg bryr meg ikke. Bare gi meg adressen til x.
& Y betyr gi meg adressen til y.
Og på det tidspunktet historien er helt konsistent med bildet trakk vi et øyeblikk siden.
>> Så jeg skal innrømme pekere, sikkert for meg da jeg først begynte å lære dette,
var definitivt en av de vanskeligste tingene å pakke meg rundt.
Men innser, særlig ettersom vi fortsette å spille med slike ting,
Hvis du bryter det ned til disse super enkle slags intellektuelt uinteressant problemer
av bare å flytte tall rundt, svaret på mye forvirring med pekere
virkelig kan utledes fra disse svært grunnleggende mekanikken.
Her er en adresse. Gå dit med stjernen.
Eller omvendt, her er et ampersand. Finne ut hva adressen faktisk er.
OK.
Så hvor er alt dette minnet kommer fra?
Vi har trukket dette bildet et par ganger, og jeg holder lovende vi vil komme tilbake til det,
men her er representasjon av datamaskinens minne
som er litt mer merket enn tavle vår her er.
Teksten segmentet på toppen representerer hva med hensyn til programmet?
[Uhørlig student respons] >> Beklager? Si det igjen.
[Student] Selve programmet. >> Selve programmet.
>> Så 0'er og 1'ere som du har samlet etter å skrive C-kode og deretter kjører Clang
og generere 0'er og 1'ere ender opp med å bli gjemt det i minnet
fordi når du dobbeltklikker på et ikon på Mac eller PC
eller kjøre en kommando som mario på ditt spørsmål, ditt 0'er og 1'ere fra disk
få lastet inn i minnet, slik at datamaskinen kan manipulere dem
og gjennomføre dem raskere.
Så initialisert data og uinitialiserte data, vil vi ikke snakke så mye om dem,
men de er bare globale variabler.
Initialisert betyr globale variabler som du ga verdier til;
uinitialisert betyr globale variabler som du ikke ennå gi verdier til.
Så er det disse miljøvariabler som jeg vil helt bølge min hånd på,
men de er der og som lagrer ting som brukernavn
og annen form for lavere nivå detaljer.
Men de saftigste bitene av minnet oppsett er dette som kalles stabelen og haugen.
Stabelen igjen, for å være klar, er minnet som brukes når funksjoner kalles,
når det er lokale variabler
og når det er parametere som er gått rundt.
Alle som skjer i bunken.
Haugen vi ikke har snakket om, men ta en gjetning som bruker haugen.
Bare en annen del av minnet.
Det skjer for å bli trukket her på toppen, men det er en vilkårlig pictorial konvensjonen.
Hvem tilsynelatende brukt minne fra haugen uker?
Det er teknisk deg, men indirekte. >> [Student] GetString.
GetString og malloc. Så her er fundamental forskjell.
>> Du vet for de siste ukene at hvis du trenger minne, bare erklære en variabel.
Hvis du trenger mye minne, erklærer en rekke rett på innsiden av funksjon din.
Men problemet vi har holdt overfor er hvis du deklarerer variabler lokalt innsiden av funksjoner,
så snart funksjonen returnerer, hva skjer med minnet og disse variablene?
Bare slags det er ikke lenger din, ikke sant? Det forsvinner bare slags konseptuelt.
Det er fortsatt fysisk der, selvsagt, men det er ikke lenger din rett til å bruke.
Dette er åpenbart problematisk hvis du ønsker å skrive funksjoner i livet
som faktisk allokere minne og ikke gi den tilbake umiddelbart.
Case in point: GetString hensikt i livet er å ha ingen anelse på forhånd
hvor stor av en streng jeg kommer til å skrive på tastaturet,
men det må være i stand til å allokere minne til å holde David eller Hallo
eller en hel essay som brukeren kan ha skrevet inn
Så GetString har brukt malloc.
Malloc derfor må bruke ikke stabelen;
i stedet den bruker dette som kalles haugen.
Det er ikke noe annerledes om minnet. Det er ikke raskere eller langsommere eller noe sånt.
Det er bare fysisk på et annet sted.
>> Men regelen er at minnet som er tildelt på haugen
vil aldri bli tatt bort fra deg før du ringer - ta en gjetning - gratis.
Derimot, noe minne du be om på bunken med bare erklære en matrise
eller erklære en variabel som vi har gjort i flere uker,
at som standard ender opp på stakken.
Og som fungerer bra 90% av tiden, men på disse sjeldnere anledninger
der du ønsker å allokere minne og holde den rundt,
så må du bruke en funksjon som malloc.
Eller vi har brukt en funksjon som GetString, som igjen bruker malloc.
La oss se hvor dette kan bryte ned og deretter ta en titt på Binky.
Vi vil komme tilbake til det i fremtiden.
Her er en super enkelt program som i de første to linjene gjør hva?
På engelsk, hva disse første to linjer med kode gjør inne i main?
[Uhørlig student respons]
Forsiktig. Det gir ikke meg adressen til x eller y.
[Student] Gir pekere til ints. >> Bra. Gi meg 2 pekere til heltall.
Med andre ord, gi meg 2 biter av minnet som jeg holder tegning i dag,
selv om jeg slettet det nå, som firkanter.
Gi meg 2 biter av minne, ett kalt x, kalt en y -
tidligere jeg ringte dem s og t - og hva er den type som del av minnet?
Det kommer til å lagre en adresse.
Det er av type int *.
>> Så adressen til en int vil til slutt leve i x,
adressen til en int vil etterhvert leve i y,
men i utgangspunktet, hva som er inni av x og y? Hvem vet? Garbage verdier.
Det har ingenting å gjøre med pekere.
Hvis vi ikke har satt noe der, hvem vet hva som er faktisk det?
Nå, x. Hva skjer her? Dette er legit nå fordi x er en peker. Det er en int *.
Så det betyr at jeg kan sette i x adressen til noen del av minnet.
Hva kommer ikke tilbake malloc? Perfekt, returnerer den adresser,
adressen til den første byte i en hel del av minnet.
Hvor mange byte er dette tilsynelatende tildeling, for eksempel i enheten?
Hva er størrelsen på en int? 4.
Hvis du tenker tilbake til uke 1, er det ikke super viktig å alltid huske det,
men i dette tilfellet er det nyttig å vite, 4 bytes.
Så dette er tildeling på haugen 4 byte
og den returnerer adressen til den første for meg vilkårlig.
Nå er det x gjør?
A * x = 42 er gjør hva?
Dersom du på dette punktet i historien vi har x, som ser ut som dette med noen søppel verdi,
dette er nå y med noen søppel verdi, nå på linje 3 har jeg tildelt fire byte.
Dette bildet ser egentlig ut som dette.
Eller mer spesifikt, hvis dette er vilkårlig adresse 123, dette er hva vår historie nå ser ut.
* X = 42 nå betyr det? Det betyr gå til adressen 123 og sette nummer 42 der.
Jeg trenger ikke å trekke disse linjene fordi vi ikke gjør strenger.
>> Jeg skal bare skrevet det slik, og bare for demonstrasjon skyld,
42 som en int slags tar opp mye plass, 4 byte.
Så det er hva som har skjedd der, men det er et problem nå.
* Y = 13. Hva kommer til å skje her?
Problemet er * y i vår forenklede verden betyr bare gå til adressen i y.
Hva er i y? Det er noen søppel verdi.
Så la oss anta at det søppel verdien er 5551212, noe sprøtt som det.
* Y del gå for å løse 5551212.
Det er som over her. Det finnes ikke, for eksempel.
Så * y får 13 betyr jeg prøver å trekke 13 her. Det eksisterer ikke.
Jeg har overskredet den delen av tavlen. Hva får jeg?
Det kryptiske meldingen segmentering feil fordi jeg prøver å sette i minnet
en verdi som 13 på et sted som ikke eksisterer.
Resten av programmet kan fungere greit, men frem til det punktet det ikke.
Så la oss prøve å fortelle denne historien.
Vi vil komme tilbake til det når vi har snakket om hex.
La oss gå tilbake til dette og konkluderer med dette som kalles Binky,
som tilbakekallingen er en Stanford professor sitte hjemme å spille med claymation,
å fortelle historien om akkurat det samme programmet.
Det er bare ca 3 minutter lang. Her har vi Binky.
[Mannlige høyttaler på video] Hei Binky, våkne opp. Det er tid for pekeren moro.
[Binky] Hva er det? Lær om pekere? Oh, goody!
[Mannlige høyttaler] Vel, for å komme i gang, antar jeg vi kommer til å trenge et par pekere.
>> [Binky] Okay. Denne koden tildeler to tips som kan peke til heltall.
[Mannlige høyttaler] Okay. Vel, jeg ser de to pekere, men de synes ikke å peke mot noe.
[Binky] Det er riktig. Begynnelsen, vil pekere ikke peke på noe.
De tingene de peker til kalles pointees, og sette dem opp er et separat trinn.
[Mannlige høyttaler] Oh, høyre, høyre. Jeg visste det. De pointees er atskilt.
Eh, så hvordan fordele du en pointee?
[Binky] Okay. Denne koden tildeler en ny heltall pointee, og denne delen setter x for å peke på det.
[Mannlige høyttaler] Hei, det ser bedre ut.
Så gjør det gjør noe. >> [Binky] Okay.
Jeg skal dereferanse pekeren x for å lagre nummeret 42 i pointee sin.
For dette trikset jeg trenger min tryllestav av dereferencing.
[Mannlige høyttaler] Din tryllestav av dereferencing? Det er flott.
[Binky] Dette er hva koden ser ut. Jeg vil bare sette opp nummeret og ... [Hvesing]
[Mannlige høyttaler] Hei ser, det det går.
Så gjør en dereferanse på x følger pilen for å få tilgang til pointee,
i dette tilfellet å lagre 42 i det.
Hei, prøv å bruke den til å lagre nummer 13 gjennom den andre pekeren, y.
[Binky] Okay. Jeg vil bare gå over her til y og få nummer 13 satt opp
og deretter ta staven av dereferencing og bare ... [Summende lyd] Whoa!
[Mannlige høyttaler] Oh hei, det gikk ikke.
>> Si, Binky, tror jeg ikke dereferencing y er en god idé
fordi sette opp pointee er et separat trinn
og jeg tror ikke vi noen gang gjorde det.
[Binky] Hmm, godt poeng.
[Mannlige høyttaler] Yeah. Vi tildelt pekeren y, men vi har aldri sett det til å peke på en pointee.
[Binky] Hmm, veldig observant.
[Mannlige høyttaler] Hei, du ser bra der, Binky.
Kan du fikse det slik at y peker til samme pointee som x? >> [Binky] Sure.
Jeg skal bruke min tryllestav av pekeren oppdrag.
[Mannlige høyttaler] Er det kommer til å bli et problem som før?
[Binky] Nei, dette ikke berører pointees.
Det endrer bare ett pekeren å peke på det samme som en annen. [Hvesing]
[Mannlige høyttaler] Oh, ser jeg. Nå y peker til samme sted som x.
Så vent. Nå y er løst. Den har en pointee.
Så du kan prøve staven av dereferencing igjen for å sende 13 over.
[Binky] Uh, okay. Her går. [Hvesing]
[Mannlige høyttaler] Hei, se på det. Nå dereferencing fungerer på y.
Og fordi pekere deler at en pointee, de begge se 13.
[Binky] Yeah, deling. Uansett.
>> Så skal vi bytte plass nå?
[Mannlige høyttaler] Oh look, vi er ute av tiden. >> [Binky] Men -
[Mannlige høyttaler] Bare husk de 3 pekeren regler.
Nummer 1, er den grunnleggende struktur som du har en peker og den peker over til en pointee.
Men pekeren og pointee er separate, og vanlig feil er å sette opp en peker
men å glemme å gi den en pointee.
Nummer 2, starter pekeren dereferencing på pekeren og følger sin pilen over
å få tilgang til pointee.
Som vi alle vet, fungerer dette bare hvis det er en pointee,
hva slags kommer tilbake til regel nummer 1.
Nummer 3, tar pekeren oppdrag en peker og endrer det
å peke på den samme pointee som en annen pekeren.
Så etter oppdraget, vil de to pekere peker til samme pointee.
Noen ganger som kalles deling.
>> Og det er alt som skal til egentlig. Bye-bye nå.
Dette er Binky. Dette er CS50. Vi får se deg neste uke. [Applaus]
>> [CS50.TV]