[Powered by Google Translate] [Pjesa 4 - më të rehatshme]
[Rob Bowden - Universiteti i Harvardit]
[Kjo është CS50. - CS50.TV]
Ne kemi një quiz nesër, në rast se ju djema nuk e di se.
Kjo është në thelb çdo gjë që ju mund të keni parë në klasë ose duhet të keni parë në klasë.
Kjo përfshin pointers, edhe pse ata janë një temë shumë të kohëve të fundit.
Ju duhet të paktën të kuptojnë nivelet e larta të tyre.
Çdo gjë që ishte zhdukur gjatë në klasë ju duhet të kuptoni për quiz.
Pra, nëse ju keni pyetje mbi to, ju mund të pyesni ata tani.
Por kjo do të jetë një sesion shumë nxënës e udhëhequr nga ku ju djema të kërkoni pyetje,
kështu që shpresojmë se njerëzit kanë pyetje.
A ka ndokush pyetje?
Po. >> [Student] Mund të ju shkoni mbi pointers përsëri?
Unë do të shkoj për pointers.
Të gjitha variablave tuaj domosdoshmërisht jetojnë në kujtesë,
por zakonisht ju mos u bëni merak për këtë dhe ju vetëm thoni x + 2 + 3 dhe y
dhe përpiluesit do të kuptoj se ku gjërat janë duke jetuar për ju.
Pasi ju jeni që kanë të bëjnë me pointers, tani ju jeni duke përdorur ato në mënyrë eksplicite adresat e memories.
Kështu që një variable të vetme do vetëm ndonjëherë të jetojnë në një adresë të vetme në çdo kohë të dhënë.
Nëse ne duam të shpallë një tregues, se çfarë është lloji do të duken si?
>> Unë dua të deklaroj një p akrep. Çfarë do të duken si tip?
[Student] int * f. Po >>. Pra, int * p.
Dhe si mund ta bëni atë pikë për të x? >> [Student] ampersand.
[Bowden] Pra simbol është quajtur fjalë adresa e operatorit.
Kështu që kur unë them dhe x është marrë adresën e kujtesës x ndryshueshme.
Kështu që tani unë kam p akrep, dhe kudo në kodin tim unë mund të përdorni p *
ose unë mund të përdorni X dhe ajo do të jetë gjë e saktë të njëjtën.
(P *). Çfarë është kjo duke bërë? Çfarë do të thotë se ylli?
[Student] Kjo do të thotë një vlerë në atë pikë. Po >>.
Pra, nëse ne shikojmë në të, ajo mund të jetë shumë i dobishëm për të nxjerrë jashtë diagramet
ku kjo është një kuti të vogël të memories për x, i cili ndodh që të ketë vlerën 4,
atëherë ne kemi një kuti të vogël të memories për p,
dhe kështu pikë të p x, kështu që ne kemi nxjerrë një shigjetë nga p në x.
Pra, kur ne themi p * ne jemi duke thënë se të shkojnë në kutinë që është p.
Yll është ndiqni arrow dhe pastaj bëni çfarë të doni me atë kuti të drejtë atje.
Kështu që unë mund të them * p = 7; dhe që do të shkojnë në kutinë që është x dhe ndryshim që në 7.
Ose unë mund të them int z = * p * 2; Kjo është konfuze, sepse kjo është yll yll.
Një yll është dereferencing p, ylli tjetër është shumëzuar me 2.
Njoftim unë mund të ketë ashtu si edhe zëvendësoi p * me x.
Ju mund të përdorni ato në të njëjtën mënyrë.
Dhe pastaj më vonë unë mund të ketë pikë p për një gjë krejtësisht të re.
Unë mund të them vetëm p = &z;
Deri tani p asnjë pikë më shumë për të x, ajo tregon për z.
Dhe çdo herë që unë të bëjë p * është e njëjtë si duke bërë z.
Pra, gjëja e dobishme në lidhje me këtë është edhe kemi filluar të hyrë në funksionet.
>> Kjo është lloj i kotë për të deklaruar një tregues që pikë për diçka
dhe pastaj ju jeni vetëm dereferencing atë
kur ju mund të ketë përdorur ndryshore origjinale për të filluar me.
Por kur ju merrni në funksionet - kështu që le të themi që ne kemi disa funksion, int foo,
që merr një tregues dhe vetëm bën p * = 6;
Ashtu siç e pamë më parë me swap, ju nuk mund të bëjë një shkëmbim efektiv dhe një funksion të veçantë
vetëm me kalimin e integers, sepse çdo gjë në C është gjithmonë kalon nga vlera.
Madje edhe kur ju jeni duke kaluar pointers që ju jeni duke kaluar nga vlera.
Kjo ndodh pikërisht kështu që këto vlera janë adresat e kujtesës.
Kështu që kur unë them foo (p), unë jam duke kaluar në treguesin në funksion foo
dhe pastaj foo është duke bërë * p = 6;
Pra, brenda këtij funksioni, p * është ende e barabartë me x,
por unë nuk mund të përdorë x brenda e atë funksion sepse nuk është scoped brenda këtij funksioni.
Pra * p = 6 është e vetmja mënyrë që unë mund të hyni në një ndryshore lokale nga një tjetër funksion.
Ose, edhe, pointers janë mënyra e vetme që unë mund të hyni në një ndryshore lokale nga një tjetër funksion.
[Student] Le të thonë se ju të kërkuar për të kthyer një akrep. Pikërisht si ju bëni këtë?
[Bowden] Kthimi një tregues si në diçka si int y = 3; kthimi dhe y? >> [Student] Yeah.
[Bowden] Okay. Ju kurrë nuk duhet ta bëjë këtë. Kjo është e keqe.
Unë mendoj se kam parë në këto slides leksion ju keni filluar duke parë këtë diagram tërë e kujtesës
ku deri këtu ju keni marrë adresën e memories 0
dhe këtu poshtë keni adresa e kujtesës 4 koncerte apo 2 në 32.
Pra, atëherë ju keni marrë disa sende dhe disa sende dhe pastaj ju duhet rafte tuaj
dhe ju keni marrë tog tuaj, që ju vetëm filluar të mësuar rreth, në rritje deri.
[Student] A nuk është grumbull mbi rafte?
>> Po. Tog është në krye, nuk është ajo? >> [Student] E pra, ai vendos 0 në krye.
[Student] Oh, ai vendos 0 në krye. >> [Student] Oh, në rregull.
Disclaimer: Kudo me CS50 ju jeni duke shkuar për të parë atë në këtë mënyrë. >> [Student] Okay.
Është vetëm se, kur ju jeni të parë duke parë oxhaqet,
si kur ju mendoni për një pirg të mendoni për gjëra të stacking në krye të njëri-tjetrit.
Pra, ne priren të rrokullisje këtë rreth në mënyrë rafte është në rritje deri si një pirg normalisht do
në vend të rafte varur poshtë. >> [Student] A nuk e mal teknikisht rriten shumë, pse?
Kjo varet nga ajo që ju them me rriten.
Rafte dhe tog gjithmonë rritet në drejtime të kundërta.
Një turrë është gjithmonë në rritje deri në kuptimin që ajo është në rritje deri
drejt adresat larta kujtesës, dhe është në rritje të grumbullosh poshtë
në atë që është në rritje drejt adresave të kujtesës të ulëta.
Kështu lartë është 0 dhe në fund është adresa e larta kujtesës.
Ata janë të dy në rritje, vetëm në kundërshtimin drejtime.
[Student] Unë vetëm do të thotë se për shkak se ju tha ju vënë rafte në fund
sepse ajo duket më intuitive, sepse për rafte të fillojë në krye të një grumbull,
tog është në krye të vetë shumë, kështu që that's - >> Yeah.
Ju gjithashtu mendoj tog si u rritur dhe më të mëdha, por më shumë rafte.
Pra rafte është ai që ne lloj i duan të tregojnë rritje deri.
Por kudo që ju shikoni përndryshe do të tregojë adresën 0 në krye
dhe adresa lartë memorie në fund, kështu që kjo është pikëpamja juaj e zakonshme e kujtesës.
>> A keni një pyetje?
[Student] A mund të na thoni më shumë rreth një grumbulli gurësh?
Po. Unë do të shkoj në se në një të dytë.
Së pari, duke shkuar prapa në pse kthimit dhe y është një gjë e keqe,
në rafte ju keni një bandë e kornizave rafte të cilat përfaqësojnë të gjitha funksionet
të cilat janë quajtur.
Pra, duke injoruar gjërat e mëparshme, në krye të rafte tuaj është gjithmonë do të jetë funksioni kryesor
pasi që është funksioni i parë që është duke u quajtur.
Dhe pastaj kur ju telefononi një tjetër funksion, rafte do të rritet poshtë.
Pra, nëse unë e quaj disa funksion, foo, dhe ajo merr vet kuadrin e saj rafte,
ajo mund të thërrasë një funksion, bar, ajo merr vet kuadrin e saj rafte.
Dhe bar mund të jetë gjithkund rekursive dhe se mund ta quajmë veten,
dhe kështu që thirrja e dytë për bar do të marrë vetë kuadrin e saj rafte.
Dhe kështu që ajo shkon në këto korniza rafte janë të gjithë variablat lokale
dhe të gjithë argumentet funksion që -
Çdo gjëra që janë në vend për këtë funksion scoped të shkuar në këto korniza rafte.
Kështu që do të thotë kur kam thënë diçka si bar është një funksion,
Unë jam vetëm duke shkuar për të deklaruar një numër të plotë dhe pastaj kthehen një tregues për atë numër të plotë.
Pra, ku bën y jetuar?
[Student] y jeton në bar. >> [Bowden] Yeah.
Diku në këtë shesh të vogël të memories është një katror littler që ka y në të.
Kur të kthehem dhe y, unë jam kthyer një tregues për këtë bllok të vogël të kujtesës.
Por atëherë kur një funksion i kthimit, korniza e saj rafte merr popped off rafte.
Dhe kjo është arsyeja pse ajo që quhet rafte.
Është si strukturën e të dhënave rafte, nëse ju e dini se çfarë është.
Ose edhe si një pirg e tabaka është gjithmonë shembull,
kryesore do të shkojë në fund, atëherë funksioni parë që ju telefononi do të shkojë në krye të kësaj,
dhe ju nuk mund të merrni Kthehu tek Qendrori deri sa të ktheheni nga të gjitha funksionet të cilat janë quajtur
që janë vendosur në krye të saj.
>> [Student] Pra, nëse ju bëni bëri kthehen dhe y, vlera që është subjekt për të ndryshuar pa paralajmërim.
Po, it's - >> [Student] Kjo mund të jetë overwritten. Po >>.
Është plotësisht - Nëse ju provoni dhe -
Kjo do të jetë një bar int * për shkak se ajo është kthyer një tregues,
kështu llojin e saj është kthimi * int.
Nëse ju provoni të përdorni vlerën e kthimit të këtij funksioni, është sjellja papërcaktuar
për shkak se tregues tregon në kujtesë e keqe. >> [Student] Okay.
Pra, çfarë nëse, për shembull, ju deklaruar int * y = malloc (sizeof (int))?
Kjo është më mirë. Po.
[Student] Ne biseduam rreth asaj se si kur ne tërhiqni gjëra për Recycle Bin tonë
ata nuk janë shuar në fakt, ne vetëm të humbasin pointers tyre.
Pra, në këtë rast nuk kemi të vërtetë fshihet vlerën apo është ende atje në kujtesë?
Për pjesën më të madhe, ajo do të jetë ende atje.
Por le të thonë se ne të ndodhë për të thirrur një funksion tjetër, Baz.
Baz do të marrë vetë kuadrin e saj rafte këtu.
Ajo do të jetë overwriting të gjitha të këtij stuff,
dhe pastaj më vonë në qoftë se ju provoni dhe të përdorni treguesin që mori para,
ajo nuk do të jetë vlera e njëjtë.
Ajo do të ketë ndryshuar vetëm sepse ju e quajti Baz funksion.
[Student] Por nuk kishte ne, ne ende do të merrni 3?
[Bowden] Në të gjitha gjasat, ju do.
Por ju nuk mund të mbështetet në atë. C thotë vetëm sjelljen e padefinuar.
>> [Student] Oh, ajo bën. Rregull.
Pra, kur ju duan të kthehen një tregues, ky është vendi ku malloc vjen në përdorim.
Unë jam me shkrim në fakt vetëm të kthehet malloc (3 * sizeof (int)).
Ne do të shkojë mbi malloc më shumë në një të dytë, por ideja e malloc është e gjitha e variablave tuaj lokale
gjithmonë të shkojnë në rafte.
Çdo gjë që është malloced shkon në grumbull, dhe ajo do të përgjithmonë dhe gjithmonë të jetë në tog
derisa ju në mënyrë eksplicite liruar atë.
Pra, kjo do të thotë se kur ju malloc diçka, ajo do të mbijetojnë pas kthimit funksion.
[Student] A do të mbijetojë, pasi programi ndalesa running? Nr >>
Mirë, kështu që ajo do të jetë aty deri sa programi është mbi të gjitha mënyra bërë running. Po >>.
Ne mund të shkojë mbi detajet e asaj që ndodh kur programi ndalesa running.
Ju mund të kenë nevojë për t'i kujtuar mua, por kjo është një gjë e ndarë krejtësisht.
[Student] Pra malloc krijon një akrep? Po >>.
Malloc - >> [Student] Unë mendoj malloc cakton një bllok i kujtesës që një tregues mund të përdorni.
[Bowden] Unë dua që diagram përsëri. >> [Student] Pra ky funksion punon, pse?
[Student] Yeah, malloc cakton një bllok i kujtesës që ju mund të përdorni,
dhe pastaj ajo kthehet adresën e bllokut të parë të kësaj memorie.
>> [Bowden] Yeah. Kështu që kur ju malloc, ju jeni grabbing disa bllok e kujtesës
që është aktualisht në tog.
Nëse tog është shumë e vogël, atëherë tog është vetëm do të rritet, dhe ajo rritet në këtë drejtim.
Pra, le të themi tog është shumë e vogël.
Atëherë ajo është gati për të rritet pak dhe të kthehen një tregues për këtë bllok që vetëm u rrit.
Kur ju stuff lirë, ju jeni bërë më shumë hapësirë ​​në tog,
kështu atëherë a vonë thirrje për malloc mund të ripërdorimin atë kujtim që ju kishte liruar më parë.
Gjëja më e rëndësishme në lidhje me malloc dhe të lirë është se ajo ju jep kontroll të plotë
gjatë jetës së këto blloqe kujtesës.
Variablat globale janë gjithmonë të gjallë.
Variablat lokale janë gjallë brenda fushëveprimit të tyre.
Sa më shpejt si ju shkoni kaluar një mbajtëse kaçurrel, variablat lokale janë të vdekur.
Malloced memorie është i gjallë kur ju dëshironi që ajo të jetë gjallë
dhe pastaj është lëshuar kur ju them se do të lirohet.
Ata në të vërtetë janë vetëm 3 lloje të memories, të vërtetë.
Ka menaxhimit automatik kujtesës, e cila është rafte.
Gjëra të ndodhë për ju automatikisht.
Kur ju thoni x int, kujtesës është ndarë për x int.
Kur x shkon jashtë fushëveprimit, kujtesës është bonifikuar për x.
Pastaj ka menaxhimi dinamike e kujtesës, e cila është ajo malloc është,
e cila është kur ju keni kontroll.
Ju vendosni kur kujtesa dinamike duhet dhe nuk duhet të ndahen.
Dhe pastaj nuk ka statike, që thjesht do të thotë se ai jeton përgjithmonë,
e cila është ajo variablave globale janë.
Ata janë vetëm gjithmonë në kujtesën.
>> Pyetje?
[Student] A mund të përcaktojë një bllok vetëm duke përdorur formatimin e teksteve kaçurrel
por jo që të ketë një deklaratë apo nëse një deklaratë kohë ose diçka të tillë?
Ju mund të përcaktojë një bllok si në një funksion, por që ka formatimin e teksteve kaçurrel shumë.
[Student] Pra, ju nuk mund të ketë vetëm si një palë të rastit të formatimin e teksteve kaçurrel në kodin tuaj
që kanë variabla lokale? >> Po, mundeni.
Brenda bar int ne mund të kemi {int y = 3;}.
Kjo është menduar të jetë e drejtë këtu.
Por që plotësisht përcakton fushëveprimin e int y.
Pas kësaj mbajtëse dytë kaçurrel, y nuk mund të përdoret më.
Ju pothuajse asnjëherë ta bëjë këtë, pse.
Getting back me atë që ndodh kur një programi përfundon,
nuk është lloj i gënjeshtrës keqkuptim / gjysma që ne të japim në mënyrë që të bëjë vetëm gjërat më të lehtë.
Ne ju them se kur ju siguroj kujtesë
ju jeni caktimin e një copë e RAM për atë ndryshueshme.
Por ju nuk jeni me të vërtetë të drejtpërdrejtë prekur RAM ndonjëherë në programet tuaja.
Nëse ju mendoni për atë, se si unë e nxora -
Dhe në fakt, në qoftë se ju shkoni nëpër në gdb ju do të shihni të njëjtën gjë.
Pavarësisht se sa herë ju drejtuar programin tuaj apo se çfarë programi ju jeni running,
rafte është gjithmonë do të fillojë -
ju jeni gjithmonë do të shohim variablave rreth oxbffff diçka adresave.
Kjo është zakonisht diku në atë rajon.
Por si mund të ketë ndoshta 2 programe pointers në kujtesën e njëjtë?
[Student] Ka disa përcaktimi arbitrar i oxbfff ku është menduar të jetë në RAM
që në fakt mund të jenë në vende të ndryshme në varësi të kur funksioni është quajtur.
Po. Termi është kujtesës virtuale.
Ideja është që çdo proces vetëm, çdo program të vetëm që po kandidon në kompjuterin tuaj
ka vet - le të supozojmë 32 bit - hapësirë ​​plotësisht i pavarur adresa.
Kjo është hapësira adresa.
Ajo ka veta plotësisht të pavarur 4 gigabajt të përdorur.
>> Pra, nëse ju drejtuar 2 programe në të njëjtën kohë, ky program sheh 4 gigabajt në vetvete,
ky program sheh 4 gigabajt në vetvete,
dhe kjo është e pamundur për këtë program për dereference një akrep
dhe përfundojnë me kujtesën nga ky program.
Dhe çfarë kujtesës virtuale është është një hartë nga një hapësirë ​​proceseve adresë
për gjërat aktuale në RAM.
Kështu që është deri në sistemin tuaj operativ të dini se,
hej, kur ky djalë dereferences pointer oxbfff, se me të vërtetë do të thotë
se ai dëshiron RAM bajt 1000,
ndërsa nëse ky program dereferences oxbfff, ai me të vërtetë dëshiron RAM bajt 10000.
Ata mund të jenë në mënyrë arbitrare larg.
Kjo është edhe e vërtetë të gjërave brenda një hapësire të vetme proceset e adresave.
Pra, si ai i sheh të gjitha 4 gigabajt për vete, por le të themi -
[Student] A çdo proces të vetëm -
Le të thonë se ju keni një kompjuter me vetëm 4 gigabajt të RAM.
A çdo proces të vetëm të shohin tërë 4 gigabajt? Po >>.
Por 4 gigabajt sheh është një gënjeshtër.
Është vetëm se mendon se i ka të gjitha kujtesën këtë, sepse ajo nuk e di se çdo proces tjetër ekziston.
Ai vetëm do të përdorin sa më shumë memorie si ajo vërtetë ka nevojë.
Sistemi operativ nuk do të japë RAM në këtë proces
në qoftë se ajo nuk është duke përdorur ndonjë kujtim në këtë rajon të tërë.
Kjo nuk do të japë atë kujtim për atë rajon.
Por ideja është që - unë jam duke u përpjekur për të menduar për - Unë nuk mund të mendoj për një analogji.
Analogjitë janë të vështirë.
Një nga çështjet e kujtesës virtuale apo një nga gjërat që e zgjidhjes
është se proceset duhet të jenë plotësisht në dijeni të njëri-tjetrit.
Dhe kështu që ju mund të shkruani ndonjë program që vetëm dereferences ndonjë akrep,
doja vetëm të shkruaj një program që thotë se * (ox1234),
Adresa dereferencing dhe kjo është kujtesa 1234.
>> Por është deri në sistemin operativ të atëhershëm të përkthyer se çfarë do të thotë 1234.
Pra, nëse ndodh 1234 të jetë një adresë e vlefshme e kujtesës për këtë proces,
si ajo është në rafte apo diçka, atëherë kjo do të kthehen vlerën e kujtesës atë adresë
sa i përket procesit të di.
Por në qoftë se 1234 nuk është një adresë e vlefshme, siç ndodh në tokë
në disa pjesë të vogël të kujtesës këtu, që është përtej rafte dhe përtej tog
dhe ju nuk e kanë përdorur me të vërtetë këtë, atëherë kjo është kur ju merrni gjëra të tilla si segfaults
sepse ju jeni të prekur kujtesës që ju nuk duhet të jetë prekur.
Kjo është gjithashtu e vërtetë -
Një 32-bit sistemit, 32 bit do të thotë që ju keni 32 bit për të përcaktuar një adresë memorie.
Kjo është arsyeja pse pointers janë 8 bytes sepse 32 bit janë 8 bytes - ose 4 bytes.
Pointers janë 4 bytes.
Kështu që kur ju shikoni një tregues si oxbfffff, që është -
Brenda çdo program të caktuar vetëm ju mund të ndërtojë çdo treguesin arbitrar,
diku nga ox0 të tëmthit 8 f's - ffffffff.
[Student] A nuk ju them se ata janë 4 bytes? Po >>.
[Student] Pastaj çdo bajt do të ketë - >> [Bowden] Hexadecimal.
Hexadecimal - 5, 6, 7, 8. Pra pointers ju do të jeni gjithmonë të parë në heksadecimal.
Kjo është vetëm se si ne klasifikimin pointers.
Çdo 2 shifrat e heksadecimal është 1 bajt.
Kështu që nuk do të jetë 8 digits hexadecimal për 4 bytes.
Pra, çdo tregues të vetme në një sistem të 32-bit do të jetë 4 bytes,
që do të thotë se në procesin e juaj ju mund të ndërtojë ndonjë arbitrare 4 bytes
dhe të bëjë një tregues nga ajo,
që do të thotë se për aq sa ajo është në dijeni, ajo mund të trajtojë një 2 të tërë ndaj 32 bytes të kujtesës.
Edhe pse ajo nuk ka të vërtetë të kenë qasje në se,
edhe në qoftë se kompjuteri juaj ka vetëm 512 MB, ajo mendon se ajo ka shumë se kujtesa.
Dhe sistemi operativ është mjaft i zgjuar se ajo vetëm do të ndajë atë që ju në të vërtetë nevojë.
Ajo nuk ka vetëm të shkuar, oh, një proces të ri: 4 koncerte.
>> Po. >> [Student] Çfarë do të thotë kau? Përse shkruani?
Kjo është vetëm simbol për heksadecimal.
Kur ju shihni një numër të fillojë me kaun, gjërat janë të njëpasnjëshme heksadecimal.
[Student] Ju u shpjeguar se çfarë ndodh kur një program përfundon. Po >>.
Çfarë ndodh kur një program përfundon është sistemi operativ
vetëm fshin mappings që ajo ka për këto adresa, dhe kjo është ajo.
Sistemi operativ tani mund të jap vetëm se kujtesa për një tjetër program për t'u përdorur.
[Student] Okay.
Kështu që kur ju ndajë diçka në tog ose variablave rafte apo globale apo ndonjë gjë,
ata të gjithë vetëm të zhduket sa më shpejt që programi mbaron
për shkak se sistemi operativ është tani të lirë për të dhënë atë kujtim për çdo proces tjetër.
[Student] Edhe pse ka ndoshta ende vlerat e shkruara në? Po >>.
Vlerat janë të ngjarë ende atje.
Është vetëm ajo do të jetë e vështirë për të marrë me ta.
Është shumë më e vështirë për të marrë me ta se ajo është për të marrë në një skedë fshihet
sepse lloji fshihet dosja e ulet atje për një kohë të gjatë dhe hard drive është shumë e madhe.
Kështu ajo do të prishësh pjesë të ndryshme të kujtesës
para se të ndodhë që të prishësh copë e kujtesës që se dosja përdorur të jetë në.
Por memorie kryesore, RAM, ju ciklit nëpërmjet një shumë të shpejtë,
kështu ajo do të jetë shumë shpejt overwritten.
Pyetjet për këtë apo ndonjë gjë tjetër?
[Student] Kam pyetje në lidhje me një temë tjetër. Mirë >>.
A ka ndokush pyetje për këtë?
>> Rregull. Tema të ndryshme. >> [Student] Okay.
Unë kam qenë duke shkuar nëpër disa nga testet praktikë,
dhe në një prej tyre është folur për sizeof
dhe vlera që kthehet apo lloje të ndryshme ndryshueshme. Po >>.
Dhe ai tha se të dy int dhe afat kthimi 4 të dyja, kështu që ata janë të dyja 4 bytes gjatë.
A ka ndonjë dallim në mes një int dhe një të gjatë, apo është e njëjta gjë?
Po, ka një dallim.
Standardi C -
Unë jam me siguri do të mess up.
Standardi C është vetëm si ajo C është, dokumentacioni zyrtar i C.
Kjo është ajo që ai thotë.
Pra standardi C vetëm thotë se një char do të përgjithmonë dhe gjithmonë të jetë 1 bajt.
Gjithçka pas kësaj - një të shkurtër është gjithmonë përkufizohet vetëm si më e madhe se ose e barabartë me një char.
Kjo mund të jetë më i madh se në mënyrë rigoroze, por jo pozitive.
Një int definohet vetëm si më e madhe se ose e barabartë me një të shkurtër.
Dhe një kohë të gjatë është përcaktuar ashtu si është më e madhe se ose e barabartë me një int.
Dhe një kohë të gjatë është më e madhe se ose e barabartë me një kohë të gjatë.
Pra, e vetmja gjë që përcakton standardi C është renditja relative e çdo gjëje.
Shuma aktuale e kujtesës që gjërat të marrin në përgjithësi është deri në zbatimin,
por kjo është goxha e mirë përcaktuar në këtë pikë. >> [Student] Okay.
Pra, pantallona të shkurtra janë pothuajse gjithmonë do të jetë 2 bytes.
Ints janë pothuajse gjithmonë do të jetë 4 bytes.
Longs gjatë janë pothuajse gjithmonë do të jetë 8 bytes.
Dhe dëshiron, kjo varet nga ajo nëse ju jeni duke përdorur një 32-bit or 64-bit të sistemit.
Kështu që një kohë të gjatë do të korrespondojnë me llojin e sistemit.
Nëse jeni duke përdorur një sistem të 32-bit si Appliance, ajo do të jetë 4 bytes.
Nëse jeni duke përdorur një 64-bit si një shumë të kompjuterëve të fundit, ajo do të jetë 8 bytes.
>> Ints janë pothuajse gjithmonë 4 bytes në këtë pikë.
Longs gjatë janë pothuajse gjithmonë 8 bytes.
Në të kaluarën, ints përdoret për të të jetë vetëm 2 bytes.
Por vini re se ky plotësisht i përmbush të gjitha këtyre marrëdhënieve më të madhe se dhe të barabartë për të.
Për aq kohë është e lejuar të përkryer që të jetë të njëjtën madhësi si një numër të plotë,
dhe kjo është e lejuar gjithashtu të jetë të njëjtën madhësi si një kohë të gjatë.
Dhe kjo ndodh pikërisht kështu që të jetë që në 99,999% e sistemeve të, ajo do të jetë e barabartë me
ose një int apo një kohë të gjatë. Kjo varet vetëm 32-bit or 64-bit. >> [Student] Okay.
Në gjithandej, sa është pika decimal të caktuar në drejtim të bit?
Ashtu si binar? Po >>.
Ju nuk keni nevojë të dini se për CS50.
Ti as nuk mësojnë që në 61.
Ju nuk mund të mësojnë që me të vërtetë në çdo kurs.
Kjo është vetëm një përfaqësim.
I harroj ndarje e saktë bit.
Ideja e pikës notuese është që ju të caktojë një numër të caktuar të bit për të përfaqësuar -
Në thelb, çdo gjë është në simbol shkencore.
Pra, ju ndajë një numër të caktuar të bit për të përfaqësuar numrin e vetë, si 1,2345.
Unë kurrë nuk mund të përfaqësojnë një numër me shifra më shumë se 5.
Pastaj ju gjithashtu ndajë një numër specifik i bit në mënyrë që ajo tenton të jetë si
ju mund të shkoni deri në një numër të caktuar, si që është eksponenti më i madh ju mund të keni,
dhe ju vetëm mund të shkojnë deri në një eksponent të caktuar,
si që është eksponenti më i vogël ju mund të keni.
>> Unë nuk e mbani mend të saktë bit mënyrë janë caktuar për të gjitha këto vlera,
por një numër i caktuar i bit janë të dedikuar për 1,2345,
një numër i caktuar i bit janë të dedikuar për eksponent,
dhe kjo është e mundur vetëm për të përfaqësuar një eksponent i një madhësie të caktuar.
[Student] Dhe një të dyfishtë? Është se si një noton ekstra të gjatë? Po >>.
Është e njëjta gjë si një float, përveç tani ju jeni duke përdorur në vend të 8 bytes 4 bytes.
Tani ju do të jetë në gjendje të përdorin shifra 9 ose 10 numra,
dhe kjo do të jetë në gjendje të shkojnë deri në 300 në vend të 100. >> [Student] Okay.
Dhe gjithandej edhe 4 bytes. Po >>.
E pra, përsëri, kjo ndoshta varet përgjithshëm mbi zbatimin e përgjithshëm,
por gjithandej janë 4 bytes, dyshe janë 8.
Dyshe janë quajtur të dyfishtë për shkak se ata janë të dyfishtë madhësinë e gjithandej.
[Student] Okay. Dhe po aty dyfishtë dyshe? Nuk ka >>.
Unë mendoj se - >> [Student] Ashtu si dëshiron të gjata? Po >>. Nuk ma ha mendja. Po.
[Student] Në testin e vitit të kaluar ka pasur një pyetje në lidhje me funksionin kryesor
pasur nevojë të jetë pjesë e programit tuaj.
Përgjigja ishte se ajo nuk duhet të jetë pjesë e programit tuaj.
Në atë situatë? Kjo është ajo që unë pashë.
[Bowden] Duket - >> [Student] Çfarë situata?
A keni problem? >> [Student] Yeah, unë mund të patjetër të tërheqë atë.
Ajo nuk duhet të jetë, teknikisht, por në thelb ajo do të jetë.
[Student] unë pashë një në një vit e ndryshme.
Ajo ishte si Vërtetë ose False: A të vlefshme - >> Oh, një file c.?
. [Student] Çdo skedar duhet të ketë c - [si folëse në një herë - pakuptueshëm]
Rregull. Pra, kjo është e veçantë.
>> Një. Fotografi c vetëm duhet të përmbajë funksione.
Ju mund të përpilojë një skedar në kodin e makinës, binar, çfarëdo,
pa qenë ekzekutues ende.
Një ekzekutiv i vlefshëm duhet të ketë një funksion kryesor.
Ju mund të shkruani 100 funksione në 1 dosje, por jo kryesore
dhe pastaj përpilojnë atë poshtë për binar,
pastaj ju shkruani një skedar që ka vetëm kryesor, por ai kërkon një bandë e këtyre funksioneve
në këtë skedar binar mbi këtu.
Dhe kështu që kur ju jeni duke e bërë të ekzekutueshme, kjo është ajo që e bën linker
është ajo kombinon këto 2 fotografi binare në një ekzekutues.
Pra, a. Fotografi c nuk ka nevojë që të ketë një funksion kryesor në të gjitha.
Dhe në bazë të kodit të mëdha ju do të shihni mijëra e dosjeve. 1 c dhe skedari kryesor.
Më shumë pyetje?
[Student] Nuk ishte një tjetër pyetje.
Ai tha se është bërë një përpilues. Vërtetë ose False?
Dhe përgjigja ishte e rreme, dhe kam kuptuar pse kjo nuk është si tingëllimë.
Por çfarë ne e quajmë të bëni nëse kjo nuk është?
Të bëjë në thelb është vetëm - Unë mund të shoh saktësisht se çfarë ajo e quan atë.
Por ajo vetëm shkon komandat.
Bërë.
Unë mund të tërheqë këtë ide. Po.
Oh, po. Të bëjë gjithashtu e bën këtë.
Kjo thotë se qëllimi i ndërmarrjes të bëjë është të përcaktojë automatikisht
cila pjesë e një programi të madh duhet të recompiled
dhe të nxjerrë komandat për të përpiluar ato.
Ju mund të bëni të bëni fotografi që janë absolutisht të madh.
Bëni duket në vulave kohore e dosjeve dhe, si e thamë më përpara,
ju mund të përpilojnë dosjet individuale poshtë, dhe kjo nuk është deri sa ju të merrni të linker
se ata janë vënë së bashku në një ekzekutues.
Pra, nëse ju keni 10 fotografi të ndryshme dhe ju bëni një ndryshim në 1 prej tyre,
atëherë çfarë të bëjë është që do të bëni është vetëm që 1 fotografi recompile
dhe pastaj relink gjithçka së bashku.
Por kjo është shumë më e dumber se kaq.
Është e deri tek ju për të krejtësisht të përcaktuar se kjo është ajo që duhet të bëni.
Ajo nga default ka aftësinë për të njohur këtë stuff pullë kohë,
por ju mund të shkruani një skedar të bëni për të bërë asgjë.
Ju mund të shkruani një skedar të bëjë në mënyrë që kur ju shkruani bërë atë vetëm të cd në një tjetër directory.
Unë kam qenë duke u irrituar sepse gjithçka litar brenda Appliance tim
dhe pastaj kam parë PDF nga Mac.
>> Kështu që unë shkoj në Finder dhe unë mund të shkoj, Connect to Server,
dhe unë të lidheni me serverin është Appliance time, dhe pastaj kam hapur deri PDF
që merr hartuar nga LaTeX.
Por unë ishte duke u frustruar, sepse çdo herë të vetme që unë e nevojshme për të rifreskoni PDF,
Unë kisha për të kopje atë në një directory të veçantë që ajo mund të ketë qasje
dhe ajo ishte duke u bezdisshëm.
Pra, në vend që unë shkroi një skedar të bërë, të cilën ju keni për të përcaktuar se si i bën gjërat.
Si ju bëni në këtë është PDF LaTeX.
Ashtu si çdo skedar tjetër të bëjë - ose I guess ju nuk e keni parë fotografi të bërë,
por ne kemi në një skedar Appliance globale bëjë që vetëm thotë,
nëse ju jeni hartimin e një skedar C, përdorni tingëllimë.
Dhe kështu këtu në dosjen time të bëjë që kam bërë unë them,
Vlerësoni këtë fotografi ju jeni do të duan për të hartuar me PDF LaTeX.
Dhe kështu kjo është LaTeX PDF që e bën hartimin.
Nuk është bërë hartimin. Është vetëm drejtimin këto komanda në rend kam specifikuar.
Pra, ajo shkon latex PDF, ajo kopje atë në directory unë dua që ajo të jetë kopjohet,
ajo CD-në directory dhe bën gjëra të tjera,
por të gjitha ajo nuk është e njohur kur një skedar ndryshime,
dhe në qoftë se ajo ndryshon, atëherë ajo do të kandidojë komandat që ajo është menduar për të kandiduar
kur ndryshimet e file. >> [Student] Okay.
Unë nuk e di se ku të bëjnë fotografi globale janë për mua për të kontrolluar atë.
Pyetje të tjera? Çdo gjë nga e kaluara kuize? Çdo gjëra akrep?
Ka gjëra delikate me pointers si -
Unë nuk jam do të jetë në gjendje të gjejnë një pyetje quiz në të -
por ashtu si ky lloj gjë.
Sigurohuni që ju kuptoni se kur them int * x * y -
Kjo nuk është saktësisht asgjë këtu, I guess.
Por si * x * y, ato janë 2 variablave që janë në rafte.
Kur them x = malloc (sizeof (int)), x është ende një ndryshore në rafte,
malloc është një bllok gjatë në grumbull, dhe ne jemi të pasur pikë x në tog.
>> Pra, diçka që në pikat rafte në tog.
Kurdo që ju malloc asgjë, ju jeni në mënyrë të pashmangshme ruajtjen atë në brendësi të një akrep.
Kështu që akrep është në rafte, blloku malloced është në tog.
Shumë njerëz të marrë hutuar dhe thonë int * x = malloc, x është në tog.
Nr Çfarë x tregon është në tog.
x vetvete është në rafte, përveç nëse për çfarëdo arsye ju keni x të jetë një variabël globale,
në të cilin rast kjo ndodh të jetë në një rajon tjetër të kujtesës.
Pra mbajtja, këto kuti diagramet dhe shigjetë janë mjaft të zakonshme për quiz.
Ose në qoftë se ajo nuk është në quiz 0, ajo do të jetë në quiz 1.
Ju duhet të dini të gjitha këto, hapat në hartimin e
që keni pasur për t'iu përgjigjur pyetjeve mbi ato. Po.
[Student] A mund të shkoj këtyre hapave - >> Sigurisht.
Para hapat dhe hartimin kemi preprocessing,
përpilimin, montimin, dhe lidh.
Preprocessing. Çfarë do të bëni?
Ajo është hapi më i lehtë në - mirë, jo si -
që nuk do të thotë se duhet të jetë e qartë, por është hapi më i lehtë.
Ju djema mund të zbatojë atë për veten tuaj. Po.
[Student] Merrni atë që ju keni në tuaj përfshin si kjo dhe ajo kopje dhe pastaj përcakton gjithashtu.
Ajo duket për gjëra të tilla si # include # define dhe,
dhe kjo vetëm kopje dhe pastat çka ata vërtetë do të thotë.
Pra, kur ju thoni # include cs50.h, preprocessor është kopjimi dhe pasting cs50.h
në atë linjë.
Kur ju thoni # define x të jetë 4, preprocessor shkon përmes programit të tërë
dhe zëvendëson të gjitha instancat e X me 4.
Pra preprocessor merr një skedar të vlefshme C dhe rezultatet e një skedar të vlefshme C
ku gjërat janë kopjuar dhe ngjit.
Kështu që tani përpilimit. Çfarë do të bëni?
[Student] Ajo shkon nga C në binar.
>> [Bowden] Ajo nuk ka shkuar gjatë gjithë rrugës për binar.
[Student] Për kodin e makinës pastaj? >> Kjo nuk është kod makine.
[Student] Kuvendit? Kuvendi >>.
Ajo shkon në Kuvend para se ajo shkon gjitha mënyra për të kodit C,
dhe gjuhët më të bëjë diçka si kjo.
Marr çdo gjuhë të nivelit të lartë, dhe në qoftë se ju jeni do të hartojnë atë,
është e mundshme që të përpilojnë në hapa.
Së pari, ai do të hartojë Python në C, atëherë ajo do të hartojë C në Kuvend,
dhe pastaj Kuvendi do të merrni përkthyer në binar.
Pra hartimin do të sjellë atë nga C në Kuvend.
Fjala hartimin zakonisht do të thotë duke e çuar atë nga një nivel më të lartë
në një gjuhë programimi të ulët të nivelit.
Pra, ky është hapi i vetëm në hartimin, ku ju të filloni me një gjuhë të nivelit të lartë
dhe do të përfundojë deri në një gjuhë të nivelit të ulët, dhe kjo është arsyeja pse është quajtur hapi hartimin.
[Student] Gjatë përpilimit, le të thonë se ju keni bërë # include cs50.h.
A do të recompile përpilues the cs50.h, si funksionet që janë në atje,
dhe përkthyer që në kodin e Kuvendit, si edhe,
apo do të kopjoni dhe ngjisni diçka që është para-Kuvendi?
cs50.h do pretty kurrë shumë të përfundojnë në Kuvend.
Stuff like prototypes funksion dhe gjërat janë vetëm për ju që të jenë të kujdesshëm.
Ai garanton se përpiluesit mund të shikoni gjëra si ju jeni duke bërë thirrje funksionet
me lloje të drejtën e kthimit dhe argumentet e duhura dhe sende.
>> Pra cs50.h do të preprocessed në dosje, dhe pastaj kur ajo e përpilimit
ajo është hedhur në thelb larg, pasi ajo e bën të sigurt se çdo gjë është duke u quajtur të saktë.
Por funksionet e përcaktuara në bibliotekë CS50, të cilat janë të ndara nga cs50.h,
ata nuk do të hartohet ndaras.
Kjo në fakt do të zbresë në hapin e lidh, kështu që ne do të merrni për të që në një të dytë.
Por së pari, çfarë është grumbulluar?
[Student] Kuvendit për binar? Po >>.
Grumbulluar.
Ne nuk e quajmë atë përpilimin sepse Kuvendi është shumë shumë një përkthim i pastër binar.
Nuk ka logjikë shumë pak në vazhdim e sipër nga Kuvendi në binar.
Është vetëm si shikuar deri në një tryezë, oh, ne kemi këtë udhëzim;
që korrespondon me binar 01.110.
Dhe kështu fotografi që në përgjithësi rezultatet janë grumbulluar. Fotografi o.
Dhe. Fotografi o janë ato që ne u thënë më parë,
si një 'file' nuk ka nevojë të ketë një funksion kryesor.
Çdo file mund të jetë përpiluar deri në një skedar. O sa kohë që ajo është një file i vlefshëm C.
Ajo mund të jetë përpiluar poshtë për të. O.
Tani, është ajo që lidh të vërtetë sjell një bandë e. Fotografi o dhe i sjell ata në një ekzekutues.
Dhe kështu që ajo lidh bën është që ju mund të mendoni për bibliotekën e CS50 si një skedar. O.
Kjo është një file binar hartuar tashmë.
Dhe kështu që kur ju hartojnë dosjen tuaj, hello.c tuaj, e cila e quan getString,
hello.c merr poshtë për të hartuar hello.o,
hello.o është tani në binar.
Ai përdor getString, kështu që ajo ka nevojë për të shkuar mbi të cs50.o,
dhe linker smooshes ato së bashku dhe kopjon getString në këtë dosje
dhe vjen me një ekzekutues që ka të gjitha funksionet që i duhen.
Pra cs50.o nuk është në fakt një file o, por është mjaft afër se nuk ka asnjë ndryshim thelbësor.
Pra lidh vetëm sjell një bandë e dosjeve bashku
se vete përmban të gjitha funksionet që unë duhet të përdorni
dhe krijon ekzekutueshme që vërtetë do të kandidojë.
>> Dhe kështu kjo është edhe ajo që ne kemi qenë të thënë para
ku ju mund të ketë 1000. fotografi c, ju hartojë të gjithë ata për të. fotografi o,
të cilat ndoshta do të marrë një kohë, atëherë ju të ndryshojë 1. fotografi c.
Ju vetëm duhet të përpiluar këtë dosje. 1 c dhe pastaj çdo gjë tjetër, relink
Lidhje gjithçka kthehet së bashku.
[Student] Kur ne jemi lidh kemi shkruar lcs50?
Po, ashtu-lcs50. Se sinjalet flamur në linker që ju duhet të lidhin në këtë bibliotekë.
Pyetje?
Kemi kaluar mbi binare përveç se 5 sekonda në leksionin e parë?
Nuk ma ha mendja.
Ju duhet të dini të gjitha OS madhe që ne kemi shkuar mbi,
dhe ju duhet të jetë në gjendje për të, nëse ju dha një funksion,
ju duhet të jetë në gjendje të thonë se kjo është e madhe O, përafërsisht. Ose mirë, i madh o është i përafërt.
Pra, nëse ju shihni mbivendosur për sythe mbi looping numër të njëjtë të gjërave,
si int i, i <n, int j, j > [Student] n katror. >> Ajo tenton të jetë n katror.
Nëse keni mbivendosur trefishtë, ajo tenton të jetë n Cubed.
Kështu që lloj i gjë që ju duhet të jetë në gjendje për të vënë në dukje menjëherë.
Ju duhet të dini lloj futje dhe lloj lloj flluskë dhe të shkrihej dhe të gjithë ata.
Është më e lehtë për të kuptuar pse ata janë ata n katror dhe n log n dhe të gjithë e që
sepse unë mendoj se ka qenë në një quiz një vit ku ne thelb ju dha
një zbatim i lloj flluskë dhe i tha: "Cili është koha drejtimin e këtij funksioni?"
Pra, nëse ju njohin atë si lloj flluskë, atëherë ju mund të thoni menjëherë n katror.
Por në qoftë se ju vetëm shikoni në atë, ju nuk keni nevojë edhe për të realizuar atë të lloj flluskë;
vetëm ju mund të thonë se kjo është bërë këtë dhe këtë. Kjo është n katror.
[Student] A ka ndonjë shembuj të vështira që ju mund të dalë me të,
si një ide të ngjashme të parafytyruar se?
>> Unë nuk mendoj se ne do të ju jap ndonjë shembull të vështira.
Lloj flluskë gjë është gati aq e vështirë sa ne do të shkojnë,
dhe madje edhe se, për aq kohë sa ju e kuptoni se ju jeni iterating mbi array
për çdo element në grup, i cili është do të jetë diçka që është n katror.
Ka pyetje të përgjithshme, si të drejtë këtu kemi - Oh.
Vetëm ditën tjetër, Doug pohoi, "unë kam shpikur një algoritmi që mund të zgjidhur një sërë
"E numrave n në O (log n) koha!"
Pra, si mund ta dimë se kjo është e pamundur?
[Përgjigja e padëgjueshme Student] >> Yeah.
Në shumë pak, ju duhet të prekë çdo element në grup,
kështu që është e pamundur për të zgjidhur një sërë -
Nëse çdo gjë është në rregull Unsorted, atëherë ju do të jeni të prekur gjithçka në grup,
kështu që është e pamundur për të bërë atë në më pak se o n.
[Student] Ju na tregoi se shembullin e të qenit në gjendje për ta bërë atë në të O n
në qoftë se ju përdorni një shumë të kujtesës. Po >>.
Dhe that's - harroj atë that's - A është numëruar lloj?
Hmm. Kjo është një algoritmi integer klasifikim.
Unë kam qenë në kërkim për emrin e veçantë për këtë se unë nuk mund të kujtohet javën e kaluar.
Po. Këto janë llojet e llojeve që mund të kryejnë gjëra në Big O e n.
Por ka kufizime, si ju mund të përdorin vetëm integers deri në një numër të caktuar.
Plus, nëse ju jeni duke u përpjekur për të zgjidhur diçka that's -
Nëse array juaj është 012, -12, 151, 4 milion,
pastaj se elementi i vetëm do të krejtësisht të prishin tërë klasifikim.
>> Pyetje?
[Student] Nëse ju keni një funksion gjithkund rekursive dhe vetëm ajo bën thirrje gjithkund rekursive
brenda një deklarate të kthimit, që është recursive bisht,
dhe kështu nuk do që përdorin shumë memorie gjatë duhur
ose të paktën do të përdorë memorie si një përsëritës krahasueshme zgjidhje?
[Bowden] Po.
Ajo do të ngjarë të jetë disi të ngadalshme, por jo të vërtetë.
Bisht rekursive është shumë e mirë.
Looking përsëri në korniza rafte, le të thonë se ne kemi kryesor
dhe ne kemi bar int (int x) ose diçka.
Kjo nuk është një funksion përsosur rekursive, por bar kthimi (x - 1).
Pra natyrisht, kjo është me të meta. Ju duhet rastet bazë dhe sende.
Por, ideja këtu është se ky është bisht rekursive,
që do të thotë kur e quan atë bar kryesor do të merrni kuadrin e saj rafte.
Në këtë kuadër rafte atje do të jetë një bllok të vogël të kujtesës
që korrespondon me x saj argument.
Dhe kështu që le të themi që ndodh kryesore për të thirrur bar (100);
Pra x do të fillojë sa më 100.
Nëse përpiluesit e pranon se ky është një funksion recursive bisht,
atëherë kur bën thirrje bar saj recursive për të penguar,
vend për të bërë një kornizë të re rafte, i cili është ku fillon rafte në rritje në masë të madhe,
në fund ajo do të kandidojë në tog dhe pastaj ju merrni segfaults
sepse memoria fillon colliding.
>> Pra, në vend të bërë vetë kuadrin e saj rafte, ajo mund të kuptojnë,
hej, unë kurrë nuk duhet të vërtetë për të ardhur përsëri në këtë kuadër rafte,
kështu që në vend që unë vetëm do të zëvendësojë këtë argument me 99 dhe pastaj të fillojë bar të gjithë.
Dhe pastaj ajo do të bëjë atë përsëri dhe ajo do të arrijë bar kthimit (x - 1),
dhe në vend të bërë një kornizë të re rafte, ai thjesht do të zëvendësojë argumentin e tij aktuale me 98
dhe pastaj hidhen përsëri në fillim të bar.
Këto operacione, duke zëvendësuar atë vlerë 1 në rafte dhe hedhur përsëri në fillim,
janë mjaft të efektshme.
Pra, jo vetëm që është përdorimi i njëjtë kujtesës si një funksion të veçantë e cila është përsëritës
sepse ju jeni vetëm duke përdorur 1 kornizë rafte, por ju nuk jeni duke vuajtur me dobësi
e të pasurit për të thirrur funksionet.
Funksionet e quajtur mund të jetë disi e shtrenjtë për shkak se ajo ka të bëjë gjithë këtë përbërje
dhe teardown dhe e gjithë kjo stuff.
Pra, kjo është e mirë recursion bisht.
[Student] Pse nuk krijon hapa të reja?
Sepse ai e kupton se nuk ka nevojë për të.
Thirrja për bar është vetëm kthimin e thirrjes rekursive.
Kështu që nuk ka nevojë të bëjë asgjë me vlerën e kthimit.
Është vetëm do të kthehen menjëherë atë.
Pra, kjo është vetëm do të zëvendësojë argumentin e vet dhe të fillojnë të gjatë.
Dhe gjithashtu, në qoftë se ju nuk keni versionin e bisht rekursive,
atëherë ju merrni të gjitha këto bare ku kur ky bar Kthim
ajo ka për t'u kthyer vlerën e saj me këtë, atëherë kjo bar kthen menjëherë
dhe vlerën e saj kthehet në këtë, atëherë ajo është vetëm do të kthehen menjëherë
dhe vlerën e saj kthehet në këtë një të tillë.
Pra, ju jeni të shpëtuar këtë popping të gjitha këto gjëra jashtë të rafte
që vlera kthimi është vetëm do të kaluar gjithë rrugën back up anyway.
Pra, pse të mos vetëm të zëvendësojë argumentin tonë me argumentin përditësuar dhe të fillojnë të gjatë?
Nëse funksioni nuk është recursive bisht, nëse ju bëni diçka si -
[Studenti] nëse bar (x + 1). Po >>.
>> Pra, nëse ju vënë atë në gjendje, atëherë ju jeni duke bërë diçka me vlerë e kthimit.
Apo edhe nëse ju vetëm bëni kthimin 2 * bar (x - 1).
Deri tani bar (x - 1) duhet të kthehen në mënyrë që ajo të llogaritur 2 herë se vlera,
kështu që tani ai ka nevojë për vetë kuadrin e saj të veçantë rafte,
dhe tani, pa marrë parasysh sa e vështirë ju provoni, ju jeni do të duhet të -
Kjo nuk është bishti rekursive.
[Student] A unë të përpiqet për të sjellë një recursion të synojnë për një bisht recursion -
[Bowden] Në një botë ideale, por në CS50 ju nuk keni për të.
Në mënyrë që të merrni recursion bisht, në përgjithësi, ju ngritur një argument shtesë
ku bar do të marrë x int y në
dhe y korrespondon me gjë fundit që ju doni të ktheheni.
Pra, atëherë kjo ju do të jeni të kthehen bar (x - 1), 2 * y.
Pra, kjo është vetëm një nivel të lartë si ju transformojnë gjërat të jenë bisht rekursive.
Por argumenti ekstra -
Dhe pastaj në fund, kur të keni arritur rastin tuaj bazë, ju vetëm të kthehet y
sepse ju keni qenë të akumulojnë gjithë kohës vlerën e kthimit që ju dëshironi.
Ju lloj kanë bërë atë iteratively por duke përdorur thirrje gjithkund rekursive.
Pyetje?
[Student] Ndoshta rreth aritmetike akrep, si kur duke përdorur vargjet. Sigurisht >>.
Aritmetike pointer.
Kur duke përdorur vargje është e lehtë, sepse vargjet janë yjet char,
chars janë përgjithmonë dhe gjithmonë një bajt vetme,
dhe kështu aritmetike tregues është i barabartë me aritmetike të rregullt, kur ju jeni që kanë të bëjnë me vargjet.
Le të them vetëm char * s = "hello".
Pra, ne kemi një bllok në kujtesë.
Ajo ka nevojë për 6 bytes sepse ju gjithmonë duhet The Terminator null.
Dhe char * s do të pikë në fillim të këtij grup.
Pra s pikë atje.
Tani, kjo është në thelb si çdo grup punon,
pavarësisht nëse kjo ishte një kthim nga malloc ose nëse kjo është në rafte.
Çdo grup në thelb është një tregues për fillimin e array,
dhe pastaj çdo operacion array, çdo Indexing, është vetëm duke shkuar në atë grup të caktuar një kompensuar.
>> Pra, kur them diçka si ve [3], kjo do të s dhe duke numëruar 3 chars in
Kështu s [3], ne kemi 0, 1, 2, 3, kështu s [3] do te referohen te kete l.
[Student] Dhe ne mund të arrijë vlerën e njëjtë duke bërë s + 3 dhe pastaj kllapat yll?
Po.
Kjo është ekuivalente me * (S + 3);
dhe që është përgjithmonë dhe gjithmonë e barabartë pa marrë parasysh atë që bëni ju.
Ju kurrë nuk duhet të përdorni sintaksë parantezë.
Ju mund të përdorni përherë * (s + 3) sintaksë.
Njerëzit kanë tendencë për të si sintaksë parantezë, edhe pse.
[Student] Pra, të gjitha vargjeve të vërtetë janë vetëm pointers.
Ka një dallim të vogël, kur them int x [4]; >> [Student] A që krijojnë e kujtesës?
[Bowden] Kjo do të krijojë 4 ints në rafte, kështu që 16 bytes përgjithshëm.
Kjo do të krijojë 16 bytes në rafte.
x nuk është ruajtur kudo.
Kjo është vetëm një simbol duke iu referuar fillimit të gjë.
Sepse ju e shpalli rrjet brenda këtij funksioni,
çfarë përpiluesit do të bëni është që vetëm të zëvendësojë të gjitha instancat e ndryshueshme x
me ku kjo ka ndodhur për të zgjedhur për të vënë këto 16 bytes.
Ajo nuk mund ta bëjë këtë me char * S sepse s është një pointer aktuale.
Ajo është e lirë për të pastaj të tregojnë për gjëra të tjera.
x është një konstante. Ju nuk mund të ketë atë pikë për një grup të ndryshme. >> [Student] Okay.
Por kjo ide, ky indeksim, është i njëjtë pavarësisht nëse kjo është një koleksion tradicional
ose në qoftë se kjo është një tregues për diçka ose nëse kjo është një tregues për një grup malloced.
Dhe në fakt, ajo është aq e barabartë se kjo është gjithashtu e njëjta gjë.
Ajo në fakt përkthehet vetëm atë që është brenda e kllapa dhe çfarë ka mbetur nga kllapa,
shton ato së bashku, dhe dereferences.
Pra, kjo është po aq e vlefshme sa * (s + 3) ose s [3].
[Student] Mund të keni pointers për të treguar 2-dimensionale vargjeve?
>> Është e vështirë. Tradicionalisht, nr.
Një 2-dimensionale array është vetëm një 1-dimensional array me disa sintaksë përshtatshëm
sepse kur them int x [3] [3], kjo është me të vërtetë vetëm 1 grup me 9 vlerave.
Dhe kështu që kur unë indeksi, përpiluesit e di se çfarë dua të them.
Nëse unë them x [1] [2], ai e di që unë dua të shkoj në rreshtin e dytë, kështu që ajo do të kaloni 3 parë,
dhe pastaj ajo dëshiron Gjëja e dytë në atë, kështu që ajo do të marrë këtë një të tillë.
Por ajo është ende vetëm një e vetme-dimensional array.
Dhe kështu që nëse kam kërkuar për të caktojë një tregues për këtë grup,
Unë do të thoja int * p = x;
Lloji i x është vetëm -
Kjo është lloj i ashpër duke thënë se x pasi ajo është vetëm një simbol dhe kjo nuk është një variabël aktuale,
por kjo është vetëm një * int.
x është vetëm një tregues për fillimin e kësaj. >> [Student] Okay.
Dhe kështu që unë nuk do të jetë në gjendje për të hyrë [1] [2].
Unë mendoj se ka sintaksë të veçantë për shpalljen një tregues,
diçka qesharake si int (* p [-. diçka absolutisht qesharake që unë nuk e di edhe.
Por ka një sintaksë për shpalljen si pointers me kllapa dhe gjëra.
Ajo nuk mund edhe të ju lejojnë të bëni këtë.
Unë mund të shikojnë prapa në diçka që do të më thoni të vërtetën.
Unë do të shikoni për më vonë, nëse ka një sintaksë për pikë. Por ju nuk do të shihni atë.
Dhe edhe sintaksa është aq arkaik se në qoftë se ju përdorni atë, njerëzit do të habitur.
Vargjeve shumëdimensionale janë mjaft të rralla si ajo është.
Ju pretty much -
E pra, nëse ju jeni duke bërë gjëra matrix se nuk do të jenë të rralla,
por në C ju jeni të rrallë do të jetë duke përdorur vargjeve shumëdimensionale.
Po. >> [Student] Le të thonë se ju keni një koleksion të vërtetë të gjatë.
>> Pra në kujtesë virtuale kjo do të duket të jetë mbi të gjitha të njëpasnjëshme,
si elemente të drejtë tjetër për njëri-tjetrin,
por në kujtesën fizike, do të jetë e mundur që kjo të jetë ndarë? Po >>.
Si punon kujtesës virtuale është vetëm ndan -
Njësia e ndarjes është një faqe, e cila ka tendencë të jetë 4 kilobytes,
dhe kështu kur një proces i thotë, hej, unë dua të përdorni këtë kujtesë,
sistemi operativ do të ndajë atë 4 kilobytes për këtë bllok të vogël të kujtesës.
Edhe në qoftë se ju përdorni vetëm një bajt vetme të vogël në gjithë bllokun e kujtesës,
sistemi operativ do të dhënë atë të plotë 4 kilobytes.
Pra, çfarë do të thotë kjo është që unë mund të ketë - le të thonë se kjo është rafte ime.
Kjo rafte mund të ndahen. Rafte im mund të jetë megabajt dhe megabajt.
Rafte im mund të jetë i madh.
Por rafte vetë duhet të jetë ndarë në faqet individuale,
që nëse ne shikojmë në gjatë këtu, le të thonë se kjo është RAM tonë,
nëse kam 2 gigabajt RAM, kjo është adresa aktuale 0 si bajt 0 RAM tim,
dhe kjo është 2 gigabajt të gjithë rrugën poshtë këtu.
Pra, kjo faqe mund të korrespondojnë me këtë bllok gjatë këtu.
Kjo faqe mund të korrespondojnë me këtë bllok gjatë këtu.
Ky i fundit mund të korrespondojnë me këtë gjatë këtu.
Pra sistemi operativ është i lirë të caktojë kujtesës fizike
për çdo faqe individual arbitrare.
Dhe kjo do të thotë se në qoftë se kjo ndodh kufitare të pushtoj një grup,
një koleksion ndodh të jetë lënë nga kjo dhe e drejta e këtij urdhri të një faqe,
pastaj se array do të jetë i ndarë në kujtesën fizike.
Dhe pastaj kur ju lë programin, kur procesi përfundon,
këto mappings merrni shuar dhe pastaj është e lirë për të përdorur këto blloqe pak për gjëra të tjera.
Më shumë pyetje?
[Student] aritmetike pointer. Oh yeah >>.
Vargjet ishin më të lehtë, por duke kërkuar në diçka si ints,
Pra, përsëri në int x [4];
Nëse kjo është një grup ose nëse kjo është një tregues për një grup prej 4 malloced integers,
ajo do të trajtohet në të njëjtën mënyrë.
[Student] Pra vargjeve janë në tog?
[Bowden] Vargjeve nuk janë në tog. >> [Student] Oh.
>> [Bowden] Ky lloj i array tenton të jetë në rafte
nëse ju shpalli atë në - injorimit variablave globale. Mos përdorni variabla globale.
Brenda një funksion që unë them int x [4];
Kjo do të krijojë një bllok 4-integer në rafte për këtë koleksion.
Por kjo malloc (4 * sizeof (int)); do të shkojë në tog.
Por pas këtë pikë unë mund të përdorni x dhe p në shumë e shumë të njëjtën mënyrë,
përveç përjashtimeve të kam thënë më parë në lidhje me ju mund të reassign p.
Teknikisht, madhësive të tyre janë disi të ndryshme, por kjo është krejtësisht e parëndësishme.
Ju kurrë nuk fakt përdorin madhësive të tyre.
P unë mund them p [3] = 2; ose x [3] = 2;
Ju mund të përdorni ato pikërisht në të njëjtën mënyrë.
Pra aritmetike treguesin tani - Po.
[Student] A nuk keni për të bërë p * nëse keni kllapa?
Kllapa janë një dereference nënkuptuar. Mirë >>.
Në fakt, edhe atë që ju jeni duke thënë se me të ju mund të merrni vargjeve shumëdimensionale
me pointers, çfarë mund të bëni ju është diçka si, le të themi, int ** pp = malloc (sizeof (int *) * 5);
Unë vetëm do të shkruaj të gjitha nga e para.
Unë nuk dua që një të tillë.
Rregull.
Çfarë kam bërë këtu është - Kjo duhet të jetë pp [i].
Kështu pp është një akrep tek një pointer.
Ju jeni mallocing pp të tregojnë për një grup prej 5 yje të mundshëm Int.
Pra, në kujtim të keni në fq rafte
Ajo do të tregojnë për një grup prej 5 blloqe të cilat janë të gjitha vetë pointers.
Dhe atëherë kur unë malloc këtu poshtë, unë malloc se secili prej këtyre pointers individuale
duhet të tregojnë për një bllok të veçantë prej 4 bytes në tog.
Pra, kjo tregon për 4 bytes.
Dhe kjo në një pikë të ndryshme 4 bytes.
>> Dhe të gjithë ata tregojnë për të tyre 4 bytes.
Kjo më jep një mënyrë për të bërë gjëra shumëdimensionale.
Unë mund të them f [3] [4], por tani kjo nuk është e njëjta gjë si vargjeve shumëdimensionale
sepse vargjeve shumëdimensionale është përkthyer [3] [4] në një të vetme kompensuar në x grup.
Kjo p dereferences, accesses indeksin e tretë, atëherë dereferences se
dhe accesses - 4 do të jetë i pavlefshëm - indeksi i dytë.
Ndërsa kur kemi pasur int x [3] [4] para se si një grup shumëdimensional
dhe kur ju të dyfishtë kllapa është me të vërtetë vetëm një dereference vetme,
ju jeni pas një tregues të vetëm dhe pastaj një kompensuar,
kjo është me të vërtetë referenca 2D.
Ju do të ndiqni 2 pointers të veçanta.
Pra, kjo gjithashtu teknikisht ju lejon të keni vargjeve shumëdimensionale
ku secili grup individ është të madhësive të ndryshme.
Kështu që unë mendoj se vargjeve shumëdimensionale dehur është ajo që quhet
që me të vërtetë gjëja e parë që mund të tregojnë për diçka që ka 10 elemente,
Gjëja e dytë që mund të tregojnë për diçka që ka 100 elemente.
[Student] A ka ndonjë kufizim për numrin e pointers ju mund të keni
duke treguar për pointers të tjera? Nr >>
Ju mund të keni int ***** p.
Kthehu tek aritmetike akrep - >> [Student] Oh. Po >>.
[Student] Nëse unë kam int *** p dhe pastaj të bëj një dereferencing dhe unë them * p është e barabartë me vlerën e kësaj,
është ajo vetëm do të bëjë 1 nivelin e dereferencing? Po >>.
Pra, nëse unë dua të hyj në gjë që treguesin e fundit është vënë në -
Pastaj ju bëni p ***. Mirë >>.
Pra, kjo është pika p deri në 1 bllok, pikë për një bllok, një tjetër pikë për të bllokut.
Pastaj në qoftë se ju bëni * p = diçka tjetër, atëherë ju jeni duke ndryshuar këtë
tani tregojnë për një bllok të ndryshme. Mirë >>.
>> [Bowden] Dhe në qoftë se këto ishin malloced, atëherë ju keni rrjedhur tani kujtesë
nëse ju ndodh që të ketë referenca të ndryshme të këtyre
që ju nuk mund të kthehet në ato ato që ju vetëm hodhën larg.
Aritmetike pointer.
int x [4]; do të ndajë një rrjet të integers 4
ku x është duke shkuar për pikë në fillim të array.
Pra, kur them diçka si x [1], unë dua që ajo të thotë të shkojnë në numër të plotë dytë në grup,
i cili do të jetë ky një.
Por me të vërtetë, kjo është 4 bytes në grup pasi kjo integer merr 4 bytes.
Kështu që një kompensuar nga 1 të vërtetë nënkupton një kompensuar nga 1
herë madhësia e çfarëdo lloji i array është.
Ky është një grup i integers, kështu që ajo di të bëjë 1 herë madhësinë e int kur ajo dëshiron për të kompensuar.
Sintaksa tjera. Mos harroni se kjo është ekuivalente me * (x + 1);
Kur them treguesin + 1, ajo që kthehet është adresa që treguesin është ruajtur
plus 1 herë madhësia e llojit të akrep.
Pra, nëse x = ox100, pastaj x + 1 = ox104.
Dhe ju mund të abuzojnë me këtë dhe thonë diçka si char * c = (char *) x;
dhe tani c do të jetë adresa e njëjtë si x.
c do të jetë e barabartë me ox100,
por c + 1 do të jetë e barabartë me ox101
pasi aritmetike tregues varet nga lloji i treguesin që ju janë shtuar për të.
Pra, c + 1, ajo duket në c, kjo është një tregues char, kështu që ajo do të shtojë 1 herë madhësinë e shkrumb,
e cila është gjithmonë do të jetë 1, kështu që ju të merrni 101,
ndërsa nëse unë bëj x, e cila është gjithashtu ende 100, x + 1 do të jetë 104.
[Student] Mund të përdorni C + +, në mënyrë për të përparuar treguesin tuaj me 1?
Po, mundeni.
Ju nuk mund të bëjë që me x x, sepse është vetëm një simbol, kjo është një konstante, ju nuk mund të ndryshoni x.
>> Por c ndodh të jetë vetëm një tregues, në mënyrë c + + është krejtësisht i vlefshëm dhe ai do të rritje deri në 1.
Në qoftë se c ishin vetëm një int *, pastaj c + + do të jetë 104.
+ + Nuk aritmetike pointer ashtu si c + 1 do të ketë bërë aritmetikë akrep.
Kjo është në fakt si një shumë gjëra të tilla si lloj Merge -
Në vend të krijuar kopje të gjëra, ju mund të kalojë në vend -
Ashtu si në qoftë se unë të kërkuar për të kaluar këtë gjysmën e grup - le të fshijë disa nga këtë.
Le të thonë se unë të kërkuar për të kaluar këtë anë të grup në një funksion.
Çfarë do që unë të kalojë në atë funksion?
Nëse unë të kalojë X, unë jam duke kaluar këtë adresë.
Por unë dua që të kalojë këtë adresë të veçantë. Pra, çfarë duhet të kalojë?
[Student] Pointer + 2?
[Bowden] Pra, x + 2. Po.
Kjo do të jetë në këtë adresë.
Ju gjithashtu shumë shpesh e shohin atë si x [2] dhe pastaj adresën e se.
Kështu që ju duhet për të marrë adresën e saj, sepse është një parantezë dereference nënkuptuar.
x [2] i referohet vlerës që është në këtë kuti, dhe pastaj ju doni adresën e atë kuti,
kështu që ju thoni dhe x [2].
Pra, kjo është se si diçka në lloj bashkojë ku ju doni të kalojë gjysmë listën për diçka
ju me të vërtetë vetëm të kalojë & x [2], dhe tani sa i përket thirrjes rekursive është i shqetësuar,
array ime e re fillon atje.
Pyetjet minutën e fundit.
[Student] Nëse ne nuk e vënë një simbol apo - çfarë është ajo quhet? Star >>?
[Student] Star. Teknikisht >>, operatori dereference, por - >> [Student] Dereference.
>> Nëse ne nuk e vënë një yll apo një simbol, çfarë ndodh në qoftë se unë them vetëm y = x dhe x është një akrep?
Çfarë është lloji i y? >> [Student] Unë do të them vetëm tregues ajo e 2.
Pra, nëse ju vetëm thoni y = x, tani x dhe y pika të njëjtën gjë. >> [Student] Pika të njëjtën gjë.
Dhe në qoftë se x është një tregues int? Kjo do të ankohen >> sepse ju nuk mund të caktoni pointers.
[Student] Okay.
Mos harroni se pointers, edhe pse ne të tërheqë ata si shigjeta,
të gjithë ata me të vërtetë dyqan - int * x - x vërtetë të gjithë është magazinimin është diçka si ox100,
që ne të ndodhë për të përfaqësuar si duke treguar për të bllokut të ruajtura në 100.
Kështu që kur unë them int * y = x, unë jam vetëm kopjimi ox100 në y,
të cilat ne jemi vetëm duke shkuar për të përfaqësuar si y, gjithashtu duke treguar ox100.
Dhe në qoftë se unë them int i = (int) x, atëherë unë do të ruajtur çdo gjë që është vlera e ox100
në brendësi të tij, por tani ajo do të interpretohet si një numër të plotë në vend të një akrep.
Por ju duhet të hedhura apo tjetër ajo do të ankohen.
[Student] Pra, do të thotë për të hedhur -
Është ajo do të hedh int x, ose e hedh int y te?
[Bowden] Çfarë?
[Student] Okay. Pas këtyre kllapa është atje do të jetë një x apo ay aty?
>> [Bowden] Ose. x dhe y janë ekuivalente. >> [Student] Okay.
Sepse ata janë të dy pointers. Po >>.
[Student] Pra, kjo do të ruajë 100 hexadecimal në formë integer? >> [Bowden] Yeah.
Por jo vlera e çfarëdo qoftë ajo tregon.
[Bowden] Yeah. >> [Student] Pra, vetëm adresa në formë integer. Rregull.
[Bowden] Nëse ju të kërkuar për të për disa arsye të çuditshme,
ju mund vetëm të merren me pointers dhe kurrë nuk merren me integers
dhe vetëm të jetë si int * x = 0.
Pastaj ju jeni do të merrni hutuar me të vërtetë dikur aritmetike pointer fillon ndodh.
Pra, numri që ata dyqan janë të pakuptimta.
Kjo është vetëm se si ju deri në fund interpretimit të tyre.
Kështu që unë jam i lirë të kopjoni ox100 nga një int * në një int,
dhe unë jam i lirë të caktojë - you're ndoshta do të merrni yelled at për të mos hedh -
Unë jam i lirë të caktojë diçka si (int *) ox1234 në këtë int * arbitrare.
Pra ox123 është vetëm si një adresë e vlefshme memorie si është dhe y.
Dhe y ndodh të kthehen diçka që është shumë e shumë ox123.
[Student] A do që të jetë një mënyrë për të vërtetë të ftohtë, për të shkuar nga heksadecimal në formë decimale,
si në qoftë se ju keni një tregues dhe ju hedhin atë si një int?
[Bowden] Ju mund të vërtetë vetëm të shtypura duke përdorur si printf.
Le të thonë se unë kam int y = 100.
Pra printf (% d \ n - si ju duhet të dini - se si të shtypura një numër të plotë, x%.
Ne vetëm do të shtypura atë si heksadecimal.
Pra, një tregues nuk është ruajtur si heksadecimal,
dhe një numër i plotë nuk është ruajtur si decimal.
Gjithçka është e ruajtur si binar.
Është vetëm se ne priren për të treguar si pointers heksadecimal
sepse ne mendojmë gjërat në këto 4-byte blloqe,
dhe adresat e kujtesës priren të jenë të njohur.
Ne jemi si, në qoftë se ajo fillon me BF, atëherë ajo që ndodh të jetë në rafte.
Pra, kjo është vetëm interpretimi ynë i pointers si heksadecimal.
Rregull. Çdo pyetje të fundit?
>> Unë do të jem këtu për një grimë, pasi në qoftë se ju keni asgjë tjetër.
Dhe kjo është fundi i kësaj.
>> [Student] Yay! [Duartrokitje]
>> [CS50.TV]