[Powered by Google Translate] [Artikel 4 - meer gemaklik] [Rob Bowden - Harvard Universiteit] [Hierdie is CS50. - CS50.TV] Ons het 'n quiz môre, in geval julle ouens het nie geweet dat. Dit is basies alles wat jy kan in die klas gesien of moet gesien word in die klas. Dit sluit pointers, selfs al is hulle 'n baie onlangse onderwerp. Jy moet ten minste verstaan ​​die hoë vlakke van hulle. Enigiets wat gegaan het om in die klas wat jy moet verstaan ​​vir die quiz. So as jy vrae het oor hulle, kan jy hulle vra nou. Maar dit gaan 'n baie student-geleide sessie wees waar julle vra vrae, so hopelik mense vrae het. Is daar iemand enige vrae? Ja. >> [Student] Kan jy weer gaan oor pointers? Ek gaan oor wysers. Al jou veranderlikes noodwendig in die geheue, maar gewoonlik bekommer julle julle nie oor wat en jy moet net sê x + 2 en y + 3 en die vertaler sal uitvind waar die dinge wat vir jou. Sodra jy met wysers, nou is jy uitdruklik die gebruik van daardie geheue-adresse. So 'n enkele veranderlike ooit sal leef net by 'n adres op enige gegewe tyd. As ons wil hê om 'n wyser om te verklaar, wat die tipe gaan lyk? Ek wil 'n wyser p te verklaar. Wat beteken die tipe lyk? [Student] int * p. >> Ja. So int * p. En hoe maak ek dit aan x? >> [Student] Ampersand. [Bowden] So ampersand genoem is letterlik die adres van die operateur. So wanneer ek sê & x dit is om die geheue-adres van die veranderlike x. So nou het ek die wyser p, en enige plek wat ek kan gebruik in my kode * p of ek kan gebruik x en dit sal presies dieselfde ding. (* P). Wat is dit besig om te doen? Wat nie beteken dat die ster? [Student] Dit beteken 'n waarde op daardie punt. >> Ja. So as ons kyk na dit, kan dit baie nuttig wees om die diagramme te teken waar dit 'n klein boks geheue vir x, wat gebeur die waarde 4 het, dan het ons 'n klein blokkie van geheue vir p, en so p punte x, sodat ons trek 'n pyl vanaf P na x. So wanneer ons sê * p ons sê gaan na die boks wat is p. Star volg die pyl en dan doen wat jy wil met dié boks reg daar. Sodat ek kan sê * p = 7; en dit sal gaan na die boks wat x en verandering wat aan 7. Of ek kon sê int z = * p * 2; Dit is verwarrend, want dit se ster,. Die een ster p ontwysing vermenigvuldig, is die ander ster deur 2. Let op ek kan net so goed die * p vervang met x. Jy kan dit gebruik in die dieselfde manier. En dan later het ek kan p punt na 'n heeltemal nuwe ding. Ek kan net sê p = &z; So nou p nie meer punte aan x; dit wys tot z. En enige tyd wat ek doen * p dit is dieselfde as die doen z. So is die nuttige ding oor hierdie is wanneer ons begin om in funksies. Dit is soort van nutteloos om 'n wyser om te verklaar dat na iets en dan is jy net ontwysing wanneer jy kon gebruik het om die oorspronklike veranderlike te begin. Maar wanneer jy in funksies - so laat ons sê ons het 'n paar funksie, int foo, wat 'n wyser en net * p = 6; Soos ons gesien het met swap, kan jy nie 'n effektiewe ruil en 'n aparte funksie net verby die heelgetalle omdat alles in C is altyd verby waarde. Selfs wanneer jy pointers is verby jy verby waarde. Dit gebeur net so dat die waardes geheue adresse. So wanneer ek sê cat (p); ek verby die wyser in die funksie foo en dan cat * p = 6; So binnekant van daardie funksie, * p is nog steeds gelyk is aan x, maar ek kan nie gebruik x binnekant van daardie funksie, want dit is nie scoped binne daardie funksie. So * p = 6 is die enigste manier wat ek kan toegang tot 'n plaaslike veranderlike van 'n ander funksie. Of, goed, wysers is die enigste manier wat ek kan toegang tot 'n plaaslike veranderlike van 'n ander funksie. [Student] Kom ons sê jy wou 'n wyser om terug te keer. Hoe presies doen jy dit? [Bowden] Terug 'n wyser as iets soos int y = 3, terugkeer & y? >> [Student] Ja. [Bowden] Goed. Jy nooit moet doen nie. Dit is sleg. Ek dink ek sien in hierdie lesing skyfies jy begin sien hierdie hele diagram van die geheue waar hier jy het geheue adres 0 en af ​​hier om jou geheue adres 4 gigs of 2 aan die 32. So dan het jy 'n paar dinge en 'n paar dinge en dan moet jy jou stapel en jy het jou hoop, wat jy net begin leer oor grootword. [Student] Is dit nie die hoop bo die stapel? Ja. Die hoop is op die top, is dit nie? >> [Student] Wel, hy het 0 bo-op. [Student] O, hy het 0 bo-op. >> [Student] O, okay. Disclaimer: Enigeplek met CS50 jy gaan om dit op hierdie manier te sien. >> [Student] Goed. Dit is net dat wanneer jy eers sien stapels, soos wanneer jy dink van 'n stapel wat jy dink van die stapel van dinge op die top van mekaar. So is ons geneig om dit om te draai om sodat die stapel is growing up soos 'n stapel normaalweg sou in plaas van die stapel hang af. >> [Student] Moenie hope tegnies grootword ook al? Dit hang af wat jy bedoel met grootword. Die stack en heap altyd in teenoorgestelde rigtings groei. Groei is altyd 'n stapel in die sin dat dit grootword na hoër geheue adresse, en die hoop groei in die sin dat dit groei tot laer geheue-adresse. Sodat die boonste 0 en die onderkant is 'n hoë geheue adresse. Hulle is albei groei, net in teenoorgestelde rigtings. [Student] Ek het net bedoel dat, omdat jy sê jy stapel op die bodem want dit lyk meer intuïtief, want vir die stapel op die top van 'n hoop om te begin, hoop is op die top van die self ook so that's - >> Ja. Jy moet ook dink die hoop as grootword en groter, maar die stapel meer so. So is die stapel is die een wat ons soort wil om te wys grootword. Maar oral waar jy kyk anders gaan adres 0 om te wys op die top en die hoogste geheue adres aan die onderkant, so dit is jou gebruiklike siening van die geheue. Het jy 'n vraag? [Student] Kan jy ons vertel meer omtrent die hoop? Ja. Ek sal in 'n tweede. Eerste, terug te gaan na waarom die terugkeer & y is 'n slegte ding, op die stapel jy 'n klomp van stapel rame wat verteenwoordig al die funksies wat geroep is. So vorige dinge te ignoreer, die top van jou stapel is altyd iets aan die hooffunksie want dit is die eerste funksie wat genoem word. En dan wanneer jy noem 'n ander funksie, is die stapel gaan af om te groei. So as ek noem 'n paar funksie, foo, en dit kry sy eie stapel raam, dit kan 'n paar funksie, bar noem dit kry sy eie stapel raam. En 'n bar kan wees rekursiewe en dit self kan noem, en sodat tweede oproep bar gaan sy eie stapel raam te kry. En so wat gaan in hierdie stapel rame is almal van die plaaslike veranderlikes en al die van die funksie argumente wat - Enige dinge wat plaaslik aan hierdie funksie scoped in hierdie stapel rame. Dus beteken dit dat wanneer ek sê iets soos bar is 'n funksie, Ek gaan net 'n heelgetal te verklaar en dan 'n wyser terug te keer na daardie heelgetal. So, waar y lewe? [Student] y woon in die bar. >> [Bowden] Ja. Iewers in hierdie klein vierkant van die geheue is 'n littler vierkant wat in die y. Wanneer ek terugkeer en y, ek 'n wyser terug na hierdie klein blokkie van die geheue. Maar dan wanneer 'n funksie opbrengste, kry sy stapel raam oopgespring die stapel af. En dit is waarom dit genoem stapel. Dit is soos die stapel data struktuur, as jy weet wat dit is. Of selfs soos 'n stapel van die bak is altyd die voorbeeld, hoof gaan om te gaan op die bodem, dan is die eerste funksie wat jy noem gaan om te gaan op die top van dat, en jy kan nie terug te kry na die hoof totdat jy terugkeer van al die funksies wat geroep is wat geplaas is op die top van dit. [Student] So as jy gedoen het nie die standaard van die & y, daardie waarde is onderhewig aan verandering sonder kennisgewing. Ja, it's - >> [student] Dit kan wees oorskryf. >> Ja. Dit is heeltemal - As jy probeer en - Dit sou ook 'n int * bar, want dit is 'n wyser terug, so sy terugkeer tipe int *. As jy probeer om die terugkeer waarde van hierdie funksie te gebruik, dit is undefined gedrag want dit wyser wys na slegte geheue. >> [Student] Goed. So, wat as jy byvoorbeeld verklaar int * y = malloc (sizeof (int))? Dit is beter. Ja. [Student] Ons het gepraat oor hoe, wanneer ons sleep dinge aan ons recycle bin hulle eintlik nie uitgewis is; ons net verloor hul wysers. Dus, in hierdie geval het ons vee eintlik die waarde of is dit nog daar in die geheue? Vir die grootste deel, dit gaan nog steeds daar wees. Maar laat ons sê ons gebeur 'n ander funksie, Baz te roep. Baz gaan sy eie stapel te kry hier. Dit gaan word vervang al hierdie dinge, en dan as jy later probeer en gebruik die wyser wat jy het voor, dit gaan nie om dieselfde waarde te wees. Dit gaan net verander omdat jy die funksie genoem Baz. [Student] Maar het ons nie, sal ons kry nog steeds 3? [Bowden] In alle waarskynlikheid, jy wil. Maar jy kan nie staatmaak op daardie. C sê net undefined gedrag. [Student] O, dit doen nie. Okay. So wanneer jy wil 'n wyser om terug te keer, dit is waar malloc kom in gebruik is. Ek eintlik skryf net terug malloc (3 * sizeof (int)). Ons gaan oor malloc meer in 'n tweede, maar die idee van malloc is al van jou plaaslike veranderlikes altyd op die stapel. Enigiets wat malloced gaan op die wal, en dit sal vir ewig en altyd op die hoop totdat jy dit uitdruklik bevry. So dit beteken dat wanneer jy malloc iets, dit gaan om te oorleef na die funksie opbrengste. [Student] Sal dit oorleef nadat die program stop hardloop? >> No. Okay, so dit gaan om daar te wees tot die program is om al die pad hardloop. >> Ja. Ons kan gaan oor die besonderhede van wat gebeur wanneer die program stop. Jy dalk nodig het om my te herinner, maar dit is 'n aparte ding heeltemal. [Student] So malloc 'n wyser skep? >> Ja. Malloc - >> [student] Ek dink malloc klassifiseer 'n blok van die geheue wat 'n wyser kan gebruik. [Bowden] Ek wil dat die diagram weer. >> [Student] So hierdie funksie werk, al is? [Student] Ja, malloc klassifiseer 'n blok van die geheue wat jy kan gebruik, en dan is dit gee die adres van die eerste blok van daardie geheue. [Bowden] Ja. So wanneer jy malloc, jy gryp n blok van die geheue wat tans in die hoop. As die hoop te klein is, dan is die hoop is net gaan om te groei, en dit groei in hierdie rigting. So kom ons sê die hoop is te klein. Dan is dit oor 'n bietjie om te groei en 'n wyser terug te keer na hierdie blok wat net gegroei. Wanneer jy free stuff, het jy meer ruimte in die hoop jy maak, so dan 'n later bel om te malloc kan onthou dat die geheue wat jy voorheen bevry. Die belangrikste ding oor malloc en gratis is dat dit gee jou volle beheer oor die leeftyd van hierdie geheue blokke. Globale veranderlikes is altyd lewe. Plaaslike veranderlikes is lewendig in hul omvang. So gou as jy verby 'n krullerige brace, die plaaslike veranderlikes is dood. Malloced geheue is lewendig wanneer jy dit wil hê om te leef en dan word vrygestel wanneer jy sê dit om vrygestel te word. Dit is eintlik die enigste 3 tipes geheue, regtig. Daar is outomatiese geheue-bestuur, wat is die stapel. Dinge gebeur outomaties vir jou. Wanneer jy sê int x, word geheue geallokeer vir int x. Wanneer X gaan uit van die omvang, is geheue herwin vir x. Dan is daar dinamiese geheue-bestuur, en dit is wat malloc is, wat is wanneer jy beheer. Jy dinamiese besluit wanneer geheue moet en moet nie toegeken word. En dan is daar statiese, wat beteken net dat dit vir ewig leef, wat is wat globale veranderlikes is. Hulle is maar net altyd in die geheue. Vrae? [Student] Kan jy definieer 'n blok net deur die gebruik van kode tussen krulhakies maar nie om te het 'n IF stelling of 'n rukkie verklaring of iets soos dit? Jy kan 'n blok te definieer soos in 'n funksie, maar dit het krullerige draadjies. [Student] So jy kan net nie soos 'n ewekansige paar van die kode tussen krulhakies in jou kode wat plaaslike veranderlikes? >> Ja, jy kan. Binne van int bar wat ons kan hê int y = 3;}. Wat veronderstel is om hier te wees. Maar wat definieer die omvang van int y heeltemal. Na die tweede krullerige brace, kan y nie meer gebruik word. Jy byna nooit doen nie, though. Om terug na wat gebeur wanneer 'n program eindig, daar is 'n soort van 'n wanopvatting / 1/2 leuen wat ons gee om net dinge makliker te maak. Ons vertel jou dat wanneer jy geheue toeken jy die toekenning van sommige stuk van RAM vir daardie veranderlike. Maar jy regtig nie direk raak RAM ooit in jou programme. As jy dink oor dit, hoe ek nader - En eintlik, as jy gaan deur in GDB jy sien dieselfde ding. Ongeag van hoeveel keer jy die program loop of watter program jy loop, die stapel is altyd gaan om te begin - jy altyd gaan veranderlikes rondom adres oxbffff iets om te sien. Dit is gewoonlik iewers in daardie streek. Maar hoe 2 programme kan moontlik verwysings na dieselfde geheue? [Student] Daar is 'n paar arbitrêre aanwysing van waar oxbfff veronderstel is om te wees op die RAM wat eintlik kan wees op verskillende plekke, afhangende van wanneer die funksie is geroep. Ja. Die term is virtuele geheue. Die idee is dat elke enkele proses, elke enkele program wat loop op jou rekenaar het sy eie - laat ons veronderstel 32 stukkies - heeltemal onafhanklik adres ruimte. Dit is die adres ruimte. Dit het sy eie heeltemal onafhanklik 4 GB om te gebruik. So as jy hardloop 2-programme gelyktydig, is hierdie program sien 4 GB vir homself, hierdie program sien 4 GB vir homself, en dit is onmoontlik vir hierdie program te dereference 'n wyser en eindig met die geheue van hierdie program. En wat virtuele geheue is, is 'n afbeelding van 'n prosesse adres ruimte werklike dinge op RAM. So dit is aan jou bedryfstelsel om te weet dat, hey, wanneer hierdie man dereferences pointer oxbfff, wat beteken dat baie dat hy wil RAM byte 1000, terwyl as hierdie program dereferences oxbfff, hy wil regtig RAM byte 10.000. Hulle kan arbitrêr ver uitmekaar wees. Dit is selfs waar van die dinge wat in 'n enkele prosesse adres ruimte. So asof dit sien al 4 GB vir homself nie, maar laat ons sê - [Student] Is elke enkele proses - Kom ons sê jy het 'n rekenaar met slegs 4 GB RAM. Is elke enkele proses sien die hele 4 GB? >> Ja. Maar die 4 GB dit sien, is 'n leuen. Dit dink net dit het al die geheue omdat dit nie weet enige ander proses bestaan. Dit sal net soveel geheue gebruik as wat dit werklik nodig het. Die bedryfstelsel is nie van plan RAM te gee aan hierdie proses as dit nie met behulp van 'n geheue in hierdie hele streek. Dit gaan nie om te gee dit geheue vir daardie streek. Maar die idee is dat ek probeer om te dink - ek kan nie dink van 'n analogie. Analogieë is hard. Een van die kwessies van virtuele geheue of een van die dinge wat dit oplos is dat prosesse moet heeltemal onbewus van mekaar. En so kan jy 'n program skryf dat net dereferences enige pointer, net soos 'n program skryf wat sê * (ox1234), en dit is ontwysing geheue adres 1234. Maar dit is tot die bedryfstelsel wat 1234 wyse te vertaal. So as 1234 gebeur met 'n geldige geheue-adres vir hierdie proses, soos dit op die stapel of iets, dan sal dit die waarde van daardie geheue adres terug so ver as die proses weet. Maar as 1234 is nie 'n geldige adres, soos dit gebeur tot grond in sommige klein stuk van die geheue hier wat is buite die stapel en buite die hoop en jy het nie regtig gebruik word wat dan, dit is wanneer jy dinge soos segfaults want jy raak geheue wat jy nie moet raak. Dit is ook waar - 'N 32-bis-stelsel, 32 stukkies beteken dat jy het 32 ​​bits 'n geheue adres te definieer. Dit is waarom pointers is 8 bytes omdat 32 stukkies 8 bytes - of 4 grepe. Pointers is 4 grepe. So wanneer jy sien 'n wyser soos oxbfffff, wat - Binne enige gegewe program wat jy kan net bou enige arbitrêre pointer, oral van ox0 te bees 8 f's - ffffffff. [Student] Het jy nie sê hulle is 'n 4 bytes? >> Ja. [Student] Dan sal elke byte - >> [Bowden] heksadesimaal. Heksadesimale - 5, 6, 7, 8. So pointers jy gaan altyd sien in heksadesimaal. Dit is net hoe ons klassifiseer wysers. Elke 2 syfers van heksadesimaal is 1 byte. So daar gaan wees 8 heksadesimale syfers vir 4 grepe. So elke enkele wyser op 'n 32-bis-stelsel gaan wees 4 bytes, wat beteken dat jy in jou proses enige arbitrêre 4 bytes kan konstrueer en maak 'n wyser uit dit uit, wat beteken dat, so ver as wat dit is bewus is, kan dit 'n hele 2 aan die 32 grepe van die geheue te spreek. Selfs al is dit nie regtig toegang tot daardie, selfs as jou rekenaar slegs 512 megagrepe het, dink dit het dat 'n groot geheue. En die bedryfstelsel is slim genoeg dat dit net sal ken wat jy werklik nodig het. Dit maak net nie gaan nie, oh, 'n nuwe proses: 4 gigs. Ja. >> [Student] Wat beteken die os is die inkomste baie beteken? Hoekom skryf jy dit? Dit is net die simbool vir heksadesimaal. As jy 'n nommer begin met die os, die opeenvolgende dinge heksadesimale. [Student] Jy het verduidelik oor wat gebeur wanneer 'n program eindig. >> Ja. Wat gebeur wanneer 'n program eindig, is die bedryfstelsel net geweet die afbeeldings dat dit vir hierdie adresse, en dit is dit. Die bedryfstelsel kan nou net dat die geheue na 'n ander program om te gebruik. [Student] Goed. So wanneer jy toeken iets op die hoop of die stapel of globale veranderlikes of enigiets, hulle almal net sodra die program eindig verdwyn omdat die bedryfstelsel is nou vry om daardie geheue te gee aan enige ander proses. [Student] Selfs al is daar waarskynlik nog waardes wat geskryf is in? >> Ja. Die waardes is waarskynlik nog steeds daar. Dit is net gaan moeilik wees om te kry op hulle. Dit is veel meer moeilik om te kry op hulle as wat dit is om te kry by 'n verwyder lêer omdat die geskrap lêer soort van daar sit vir 'n lang tyd en die hardeskyf is 'n baie groter. So dit gaan die verskillende dele van die geheue te oorskryf voordat dit gebeur die stuk van die geheue dat lêer wat gebruik word om op te oorskryf. Maar die hoof geheue, geheue, jy siklus deur middel van 'n baie vinniger, so dit gaan om baie vinnig te oorskryf. Vrae oor hierdie of enige iets anders? [Student] Ek het vrae oor 'n ander onderwerp. >> Goed. Is daar iemand vrae het oor hierdie? Okay. Ander onderwerp. >> [Student] Goed. Ek gaan deur 'n paar van die praktyk te toets, en in een van hulle was in gesprek oor die sizeof en die waarde wat dit terugkeer of verskillende veranderlike tipes. >> Ja. En dit het gesê dat beide int en lang beide opbrengs 4 so, hulle is beide 4 bytes lank. Is daar 'n verskil tussen 'n int en 'n lang, of is dit dieselfde ding? Ja, daar is 'n verskil. Die C-standaard - Ek waarskynlik gaan opfok. Die C-standaard is net soos wat C is, die amptelike dokumentasie van C. Dit is wat dit sê. So sê die C-standaard net dat 'n kar sal vir ewig en altyd 1 byte. Alles daarna - 'n kort is altyd net gedefinieer as groter as of gelyk aan 'n char. Dit kan wees streng groter as, maar nie positief nie. 'N int is net gedefinieer as groter as of gelyk aan 'n kort. En 'n lang is net gedefinieer as groter as of gelyk aan 'n int. En 'n lang lang groter as of gelyk aan 'n lang. Dus is die enigste ding wat die C-standaard bepaal is die relatiewe ordening van alles. Die werklike bedrag van die geheue dat dinge neem, is oor die algemeen tot implementering, maar dit is redelik goed gedefinieer op hierdie punt. >> [Student] Goed. So kortbroek is byna altyd gaan 2 grepe. Ints is byna altyd gaan wees 4 grepe. Long longs is byna altyd gaan wees 8 grepe. En verlang, dit hang af of jy met behulp van 'n 32-bis of 'n 64-bis-stelsel. So 'n lang gaan stem ooreen met die tipe van die stelsel. As jy met behulp van 'n 32-bis-stelsel soos die Appliance, gaan dit 4 bytes. As jy met behulp van 'n 64-bis soos 'n baie van die onlangse rekenaars, gaan dit 8 grepe. Ints is byna altyd 4 grepe op hierdie punt. Long longs is byna altyd 8 grepe. In die verlede, ints gebruik net 2 grepe. Maar let op dat dit heeltemal voldoen aan al van hierdie verhoudings van meer as en gelyk aan. So lank is perfek toegelaat word om die dieselfde grootte as 'n heelgetal wees, En dit is ook toegelaat om die dieselfde grootte as 'n lang lang. En dit gebeur net so te wees dat 99,999% van stelsels, dit gaan gelyk wees aan óf 'n int of 'n lang lang. Dit hang net op 32-bis of 64-bis. >> [Student] Goed. In dryf, hoe is die desimale punt aangewys in terme van stukkies? Soos binêre? >> Ja. Jy hoef nie om te weet dat vir CS50. Jy hoef nie eens leer dat in 61. Jy het nie regtig leer in enige kursus. Dit is net 'n voorstelling. Ek vergeet die presiese bietjie toewysings. Die idee van die floating point is wat jy ken 'n spesifieke aantal bisse te stel - Basies, alles is in wetenskaplike notasie. So jy ken 'n spesifieke aantal bisse die getal self voor te stel soos 1,2345. Ek kan nooit met meer as 5 syfers verteenwoordig 'n aantal. Dan moet jy ook die toekenning van 'n spesifieke aantal bisse, sodat dit is geneig om te wees soos jy kan net tot 'n sekere aantal, soos wat is die grootste eksponent wat jy kan hê, en jy kan net gaan af na 'n sekere eksponent, soos wat is die kleinste eksponent wat jy kan hê. Ek onthou nie die presiese manier waarop bisse word opgedra aan al hierdie waardes, maar 'n sekere aantal bisse is toegewyd tot 1,2345, nog 'n sekere aantal bisse word gewy aan die eksponent, en dit is net moontlik om 'n eksponent van 'n sekere grootte te stel. [Student] En 'n dubbele? Is dit soos 'n ekstra lang float? >> Ja. Dit is dieselfde ding as 'n float behalwe nou jy gebruik 8 grepe in plaas van 4 grepe. Nou sal jy in staat wees om 9 syfers of 10 syfers te gebruik, en dit sal in staat wees om te gaan na 300 in plaas van 100. >> [Student] Goed. En vlotte is ook 4 grepe. >> Ja. Wel, weer, dit hang af waarskynlik algeheel op algemene implementering, maar dryf is 4 grepe, dubbelspel is 8. Dubbelspel is dubbel genoem omdat hulle is dubbel die grootte van dryf. [Student] Goed. En daar is verdubbel dubbel? >> Daar is nie. Ek dink - >> [student] Soos lang longs? >> Ja. Ek dink nie so nie. Ja. [Student] Op verlede jaar se toets was daar 'n vraag oor die hooffunksie om deel te wees van jou program. Die antwoord was dat dit nie om deel te wees van jou program. In watter situasie? Dit is wat ek gesien het. [Bowden] Dit blyk - >> [student] Watter situasie? Het jy die probleem? >> [Student] Ja, ek kan beslis trek dit. Dit hoef nie te wees nie, tegnies, maar basies is dit gaan wees. [Student] Ek het iemand gesien wat op 'n ander jaar. Dit was soos 'Waar of Onwaar: 'n Geldige >> O, 'n C-lêer? [Student] Enige c-lêer moet - [beide praat in 'n keer - onverstaanbaar] Okay. So dit is apart. 'N c-lêer moet net funksies te bevat. Jy kan stel 'n lêer in die masjien-kode, binêre, ongeag, sonder dat dit uitvoerbaar nie. 'N Geldige uitvoerbare moet 'n hoof funksie. Jy kan skryf 100 funksies in 1 lêer, maar geen hoof en dan stel dat down binêre, dan moet jy 'n ander lêer wat slegs belangrikste skryf, maar dit noem 'n klomp van hierdie funksies in hierdie binêre lêer hier. En so wanneer jy die uitvoerbare maak, dit is wat die koppelingshistoon doen is dit kombineer hierdie 2 binêre lêers in 'n uitvoerbare. So 'n C-lêer hoef nie 'n hoof funksie te hê. En op groot-kode basisse wat jy sal sien duisende c lêers en 1 hoof lêer. Nog vrae? [Student] Daar was 'n ander vraag. Daar word gesê dat maak, is 'n vertaler. WAAR of ONWAAR? En die antwoord was vals, en ek verstaan ​​hoekom dit is nie soos kletteren. Maar wat noem ons maak as dit nie? Maak is basies net - ek kan sien presies wat dit noem dit. Maar dit loop net bevele. Maak. Ek kan trek hierdie up. Ja. O, ja. Maak doen ook. Dit sê die doel van die fabrikaat nut is om outomaties te bepaal wat stukkies van 'n groot program moet word gehercompileerd en die opdragte uitreik om hulle te hercompileren. Jy kan maak maak lêers wat absoluut groot. Maak kyk na die tyd stempels van lêers en, soos ons vantevore gesê het, jy kan stel individuele lêers af, en dit is nie totdat jy by die koppelingshistoon dat hulle saam in 'n uitvoerbare. So as jy het 10 verskillende lêers en jy maak 'n verandering aan 1 van hulle, dan Watter maak is gaan om te doen is net heropstel dat 1 lêer en dan relink alles saam. Maar dit is baie dommer as dit. Dit is vir u om te definieer dat dit is wat dit moet doen. Dit by verstek die vermoë het om hierdie tyd stempel dinge te erken, maar jy kan 'n fabrikaat lêer skryf om iets te doen. Jy kan skryf 'n maak-lêer, sodat wanneer jy tik maak dit net cd's na 'n ander gids. Ek was gefrustreerd omdat ek ryg alles binnekant van my Appliance en dan sal ek sien die PDF van die Mac. So ek gaan Finder en ek kan gaan doen, Connect met die bediener en die bediener Ek verbind my Appliance, en dan het ek die PDF wat kry saamgestel deur LaTeX. Maar ek is gefrustreerd omdat elke enkele keer wat ek nodig het om die PDF te verfris, Ek het om dit te kopieer na 'n spesifieke gids wat dit kan toegang tot en dit is om irriterende. So in plaas ek 'n make-lêer, wat jy het om te bepaal hoe dit maak dinge geskryf het. Hoe maak jy in hierdie PDF LaTeX. Net soos enige ander fabrikaat lêer - of ek dink jy nie gesien het nie die fabrikaat lêers, maar ons het in die Appliance 'n globale fabrikaat lêer wat net sê, as jy die opstel van 'n C-lêer, gebruik kletteren. En so hier in my fabrikaat lêer wat ek maak wat ek sê, hierdie lêer wat jy gaan om te wil hê om saam te stel met PDF LaTeX. En dus is dit PDF LaTeX wat doen die opstel. Maak, is nie die opstel van. Dit is net met hierdie opdragte in die volgorde wat ek gespesifiseer. So is dit loop PDF LaTeX, kopieer dit na die gids wat ek wil dit gekopieer word, dit cd's na die gids en doen ander dinge, maar al wat dit doen word erken wanneer 'n lêer verander, en indien dit verander, dan sal dit die opdragte wat dit veronderstel is om te hardloop hardloop wanneer die lêer verander. >> [Student] Goed. Ek weet nie waar die globale fabrikaat lêers is vir my om dit te check. Ander vrae? Enigiets uit die verlede vasvrae? Enige pointer dinge? Daar is subtiele dinge met wysers soos - Ek gaan nie in staat wees om 'n quiz vraag te kry op dit - maar net soos hierdie soort van ding. Maak seker dat jy verstaan ​​dat as ek sê int * x * y - Dit is nie presies hier iets, dink ek. Maar soos * x * y, dit is 2 veranderlikes wat op die stapel. Toe ek sê x = malloc (sizeof (int)), x is nog steeds 'n veranderlike op die stapel, malloc 'n blok oor in die hoop, en ons is met x punt aan die hoop. So iets op die stapel punte aan die hoop. Wanneer jy malloc enigiets, jy noodwendig om dit te stoor binnekant van 'n wyser. So dat die wyser is op die stapel, die malloced blok is op die hoop. 'N baie mense kry verward en sê int * x = malloc, x is op die hoop. No. Wat x dui op is op die hoop. x self is op die stapel, tensy vir watter rede ookal jy x het 'n globale veranderlike, in welke geval dit gebeur te wees in 'n ander streek van die geheue. So hou nie, hierdie boks en boog diagramme is redelik algemeen vir die quiz. Of as dit nie op quiz 0, sal dit op quiz 1. Jy moet weet al hierdie, die stappe in die opstel want jy het vrae oor daardie te beantwoord. Ja. [Student] Kan ons gaan oor daardie stappe - >> Sure. Voordat stappe en die opstel van ons het preprocessing, die samestelling, vervaardiging, en koppel. Actuatoren. Wat beteken dit? Dit is die maklikste stap in - wel, nie soos - dit beteken nie dat dit moet duidelik wees, maar dit is die maklikste stap. Julle ouens kan implementeer dit self. Ja. [Student] Neem wat jy in jou sluit soos hierdie en dit kopieer en dan ook bepaal. Dit lyk vir dinge soos # include # define, en dit net kopieer en plak wat daardie eintlik beteken. So wanneer jy sê # include cs50.h, is die voorverwerker kopieer en plak cs50.h in daardie lyn. Wanneer jy sê # define x 4, die voorverwerker gaan deur die hele program en vervang alle gevalle van x met 4. So het die voorverwerker neem 'n geldige C lêer en uitsette 'n geldige C lêer waar dinge is gekopieer en geplak. So nou die opstel van. Wat beteken dit? [Student] Dit gaan vanaf C na binêre. [Bowden] Dit gaan nie al die pad na binêre. [Student] To Machine-kode dan? >> Dit is nie masjien-kode. [Student] Vergadering? >> Vergadering. Dit gaan na die Vergadering voordat dit gaan al die pad na C-kode, en die meeste tale doen iets soos hierdie. Kies 'n hoë-vlak taal, en as jy gaan om dit op te stel, dit is waarskynlik te stel in stappe. Eerste dit gaan Python te stel aan C, dan is dit gaan C op te stel Vergadering, en dan Vergadering gaan om te vertaal na binêre. So die opstel gaan dit vanaf C na Vergadering bring. Die woord opstel van beteken gewoonlik om dit van 'n hoër vlak na 'n laer vlak programmeertaal. So, dit is die enigste stap in die samestelling waar jy begin met 'n hoë-vlak taal en eindig in 'n lae-vlak taal, en dit is waarom die stap is genoem die opstel van. Student] Tydens die opstel van, laat ons sê dat jy gedoen het # include cs50.h. Sal die samesteller heropstel die cs50.h, soos die funksies wat daar is, en vertaal dit in Vergadering kode sowel, of sal dit kopieer en plak iets wat pre-Vergadering? cs50.h sal pretty much nooit 'n einde in die Vergadering. Denke soos funksie prototipes en dinge is net vir jou om versigtig te wees. Dit waarborg dat die samesteller dinge kan kyk soos jy 'n beroep funksies met die regte opbrengs tipes en die regte argumente en stuff. So cs50.h preprocessed word in die lêer, en dan wanneer dit die samestelling van Dit is basies weggegooi nadat dit maak seker dat alles korrek genoem. Maar die funksies gedefinieer in die CS50 biblioteek, wat apart van cs50.h dié sal nie afsonderlik saamgestel word. Wat eintlik afkom in die koppeling stap, so ons sal kry in 'n tweede. Maar eers, wat is die samestelling? [Student] Vergadering binêre? >> Ja. Byeenkoms. Ons noem dit nie die opstel omdat Vergadering is pretty much 'n suiwer vertaling van binêre. Daar is baie min logika gaan van Vergadering na binêre. Dit is net soos om in 'n tabel, oh, ons het hierdie opdrag; wat ooreenstem met binêre 01.110. En so het die lêers wat monteerwerk algemeen uitsette is. O lêers. En o lêers. Is wat ons het gesê voor, hoe om 'n lêer hoef nie 'n hoof funksie te hê. Enige lêer kan saamgestel word na 'n o-lêer. So lank as wat dit is 'n geldige C-lêer. Dit kan saamgestel word. O. Nou, 'n skakel is wat werklik bring 'n klomp van die o lêers en bring hulle tot 'n uitvoerbare. En wat skakeling doen wat jy kan dink van die CS50 biblioteek as 'n o-lêer. Dit is 'n reeds saamgestel binêre lêer. En so wanneer jy stel jou lêer, jou hello.c, wat noem GetString, hello.c kry saamgestel na hello.o, hello.o is nou in binêre. Dit maak gebruik van GetString, so is dit nodig om oor te gaan na cs50.o, en die koppelingshistoon smooshes hulle saam en skryf GetString in hierdie lêer en kom uit met 'n uitvoerbare wat al die funksies wat dit nodig het. So cs50.o is nie eintlik 'n O lêer, maar dit is naby genoeg dat daar geen fundamentele verskil. So koppel net bring 'n klomp van die lêers saam wat afsonderlik bevat al die funksies wat ek nodig het om te gebruik en skep die uitvoerbare wat eintlik loop. En so het dit is ook wat ons het gesê voor waar jy 1000 kan hê. c lêers, jy stel om hulle almal te o lêers. wat sal waarskynlik 'n rukkie neem, dan moet jy verander 1 c lêer. Jy hoef net dat 1. C lêer en dan relink alles te hercompileren, skakel alles weer saam. [Student] Wanneer ons 'n skakel ons skryf lcs50? Ja, so-lcs50. Dit vlag seine na die koppelingshistoon wat jy moet koppel in daardie biblioteek. Vrae? Het ons deurgetrek binêre anders as wat 5 sekondes in die eerste lesing? Ek dink nie so nie. Wat jy moet weet van die groot Os wat ons het oorgevaar en, en jy moet in staat wees om as ons aan julle gegee het 'n funksie, jy moet in staat wees om te sê dit is groot O, grof. Of goed, groot-O is grof. So as jy sien geneste vir loops herhaling oor die dieselfde aantal van die dinge, soos int i, i > [student] n kwadraat. >> Dit is geneig om te wees n kwadraat. As jy triple geneste, is dit geneig is om te wees n blokkies gesny. So daardie soort van ding wat jy moet in staat wees om uit te wys onmiddellik. Jy moet invoeging soort en borrel soort te ken en te sorteer en al daardie saamsmelt. Dit is makliker om te verstaan ​​waarom hulle dié n kwadraat en n log n en al want ek dink daar was een jaar waar ons basies wat jy gegee het op 'n quiz 'n implementering van die borrel soort en gesê: "Wat is die looptyd van hierdie funksie?" So as jy dit herken as borrel soort, dan kan jy dadelik sê n kwadraat. Maar as jy net kyk na dit, het jy nie eens nodig om te besef dit se borrel soort; jy kan net sê hierdie en dit doen. Dit is n kwadraat. [Student] Is daar enige moeilike voorbeelde wat jy kan kom met, soos 'n soortgelyke idee van die uitzoeken? Ek dink nie ons sal gee jou 'n moeilike voorbeelde. Die borrel soort ding is omtrent so moeilik soos wat ons sou gaan, en selfs dat so lank as wat jy verstaan ​​dat jy iterating oor die skikking vir elke element in die skikking, wat gaan iets wat se N-kwadraat. Daar is 'n algemene vrae, soos hier wat ons het - Oh. Net die ander dag, Doug beweer, "Ek het uitgevind 'n algoritme wat kan 'n verskeidenheid sorteer "Van n getalle in O (log n) tyd!" So, hoe weet ons dit is onmoontlik? [Onhoorbaar student reaksie] >> Ja. Op die heel minste, moet jy elke element in die skikking aan te raak, so dit is onmoontlik om 'n skikking te sorteer - As alles is in unsorted einde, dan is jy gaan raak alles in die skikking, so dit is onmoontlik om dit te doen in minder as O van n. [Student] Jy het vir ons gewys dat die voorbeeld van in staat is om dit te doen in die O van n as jy gebruik maak van 'n baie van die geheue. >> Ja. En that's - ek vergeet wat that's - Is dit tel soort? Hmm. Dit is 'n heelgetal sorteringsalgoritme. Ek was op soek vir die spesiale naam vir hierdie wat ek nie kon onthou verlede week. Ja. Dit is die aard van die spesies wat dinge kan bereik in die groot O van n. Maar daar is beperkings, soos jy kan slegs heelgetalle gebruik tot 'n sekere aantal. Plus as jy probeer om iets that's te sorteer - As jou skikking is 012, 12, 151, 4 miljoen, dan daardie enkele element gaan heeltemal te ruïneer die hele sorteer. Vrae? [Student] As jy 'n rekursiewe funksie en dit net maak die rekursiewe oproepe binne 'n terugkeer verklaring, wat se stert rekursiewe, en so sal dit nie gebruik meer geheue tydens runtime of sou dit ten minste vergelykbaar geheue gebruik as 'n iteratiewe oplossing? [Bowden] Ja. Dit sou waarskynlik ietwat stadiger, maar nie regtig. Stert rekursiewe is redelik goed. Ons sien daarna weer op stapel rame, laat ons sê dat ons hoof en ons het 'n int bar (int x) of iets. Dit is nie 'n perfekte rekursiewe funksie, maar terugkeer bar (x - 1). So natuurlik, dit is gebrekkig. Jy moet 'n basis gevalle en stuff. Maar die idee hier is dat hierdie is 'n stert rekursiewe, wat beteken dat wanneer hoof oproepe bar dit gaan sy stapel raam te kry. In hierdie stapel raam daar gaan 'n klein blokkie van die geheue wat ooreenstem met sy argument x. En so kom ons sê belangrikste gebeur bar (100) te roep; So x gaan begin as 100. Indien die vertaler erken dat dit 'n stert rekursiewe funksie, dan wanneer bar maak sy rekursiewe oproep te staaf, in plaas van die maak van 'n nuwe stapel raam, en dit is waar die stapel begin grootliks groei, uiteindelik sal dit loop in die hoop en dan kry jy segfaults want die geheue begin bots. So in plaas van om sy eie stapel raam, kan dit besef, hey, ek het nooit regtig nodig het om terug te kom na hierdie stapel raam, so maar ek sal net hierdie argument met 99 vervang en dan begin bar alles oor. En dan sal dit doen dit weer en dit sal terugkeer bar bereik (x - 1), en in plaas van die maak van 'n nuwe stapel raam, sal dit vervang net die huidige argument met 98 en dan terug spring na die begin van die bar. Dié bedrywighede, wat 1 waarde op die stapel te vervang en spring terug na die begin, is redelik doeltreffend. Dus nie net is dit dieselfde geheue gebruik as 'n aparte funksie wat iteratiewe omdat jy slegs met behulp van 1 stapel raam, maar jy is nie die lyding van die nadele om funksies uit te roep. Oproep funksies kan 'n bietjie duur, want dit het al hierdie setup te doen en tear down en al hierdie dinge. So hierdie Staartrecursie is goed. [Student] Waarom word dit nie nuwe stappe doen? Omdat dit besef dit nie hoef te. Die oproep tot bar is net die terugkeer van die rekursiewe oproep. Sodat dit nie nodig om iets te doen het met die terugkeer waarde. Dit is net gaan om onmiddellik stuur dit terug. So dit is net gaan om sy eie argument te vervang en begin oor. En ook, as jy nie die stert rekursiewe weergawe, dan kry jy al die bars waar wanneer hierdie bar terug dit het die waarde daarvan om terug te keer na hierdie een, dan is dit bar onmiddellik terug en dit gee die waarde daarvan aan hierdie een, dan is dit net gaan om onmiddellik terug en die waarde daarvan terug aan hierdie een. So jy spaar knal al hierdie dinge af van die stapel sedert die terugkeer waarde is net gaan al die pad terug tot in elk geval. So hoekom nie net vervang ons argument met die opgedateerde argument en begin oor? As die funksie is nie stert rekursiewe, as jy nie iets soos - [Student] indien bar (x + 1). >> Ja. So as jy dit in die toestand is, dan is jy om iets te doen met die terugkeer waarde. Of selfs as jy net doen terugkeer 2 * Bar (x - 1). So nou bar (x - 1) moet om terug te keer sodat dit 2 keer dat die waarde te bereken, so nou is dit nie nodig sy eie aparte stapel raam, en nou, maak nie saak hoe hard jy probeer nie, jy gaan nodig om - Dit is nie stert rekursiewe. [Student] Sou ek probeer om 'n rekursie te bring om te streef na 'n stert rekursie - [Bowden] In 'n ideale wêreld, maar in CS50 jy nie. Ten einde stert rekursie te kry, oor die algemeen, moet jy die opstel van 'n bykomende argument waar die bar sal int x y en y ooreenstem met die uiteindelike ding wat jy wil om terug te keer. So dan is dit jy gaan om terug te keer bar (x - 1) 2 * y. So dit is net 'n hoë-vlak hoe jy transformeer dinge te wees stert rekursiewe. Maar die ekstra argument - En dan aan die einde wanneer jy bereik jou basis geval, jy net terugkom y omdat jy die opbou van die hele tyd die terugkeer waarde wat jy wil. Jy soort van het is om dit te doen iteratief maar met behulp van rekursiewe oproepe. Vrae? [Student] Miskien oor pointer rekenkunde, soos wanneer met behulp van toue. >> Sure. Pointer rekenkunde. By die gebruik van snare dit is maklik omdat snare char sterre, karakters is vir ewig en altyd 'n enkele greep, en so wyser rekenkunde is gelykstaande aan 'n gereelde rekenkundige wanneer jy met stringe. Laat ons net sê char * s = "hallo". So ons het 'n blok in die geheue. Dit benodig 6 grepe omdat jy altyd die null terminator nodig. En char * s gaan om te verwys na die begin van die skikking. So se punte daar. Nou, dit is basies hoe om 'n verskeidenheid werk, ongeag of dit was 'n opgawe deur malloc of dit is op die stapel. Enige skikking is basies 'n wyser na die begin van die skikking, en dan enige skikking werking, enige indeksering, is net gaan in daardie skikking 'n sekere geneutraliseer. So as ek sê iets soos s [3]; dit gaan en toe 3 karakters. So s [3], het ons 0, 1, 2, 3, so s [3] gaan om te verwys na hierdie l. [Student] En ons kon dieselfde waarde bereik deur te doen s + 3 en dan hakies ster? Ja. Dit is gelykstaande aan * (s + 3); en dit is vir ewig en altyd gelyk maak nie saak wat jy doen nie. Jy hoef nooit die bracket sintaksis te gebruik. Kan jy altyd gebruik om die * (s + 3) sintaksis. Mense is geneig om die bracket sintaksis te hou, al is. [Student] So was dan al skikkings is eintlik net wysers. Daar is 'n effense onderskeid wanneer ek sê int x [4]; >> [student] wat die skep van die geheue? [Bowden] Dit gaan 4 ints op die stapel te skep, so 16 bytes algehele. Dit gaan 16 bytes te skep op die stapel. x is nie gestoor word op enige plek. Dit is net 'n simbool verwys na die aanvang van die saak. Omdat jy die skikking verklaar binnekant van hierdie funksie, wat die vertaler gaan doen is net vervang alle gevalle van die veranderlike x waar dit gebeur het om te kies hierdie 16 bytes te sit. Dit nie kan doen met char * s omdat s is 'n werklike wyser. Dit is gratis om te wys na ander dinge. x is 'n konstante. Jy kan nie dit punt na 'n ander skikking. >> [Student] Goed. Maar hierdie idee, hierdie indeksering, is dieselfde, ongeag of dit is 'n tradisionele skikking of as dit 'n wyser na iets of indien dit is 'n wyser na 'n malloced skikking. En in die waarheid te sê, dit is so gelyk dat dit ook dieselfde ding. Dit is eintlik net beteken wat binnekant van die hakies is en wat oorbly van die hakies, voeg hulle saam en dereferences. So dit is net so geldig soos * (s + 3) of s [3]. [Student] Kan jy wysers wys na 2-dimensionele skikkings? Dit is moeiliker. Tradisioneel, no. 'N 2-dimensionele skikking is net 'n 1-dimensionele skikking met 'n paar gerieflike sintaksis want as ek sê int x [3] [3], dit is regtig net 1 skikking met 9 waardes. En so toe ek indeks, is die samesteller weet wat ek bedoel. As ek sê x [1] [2], dit weet ek wil om te gaan na die tweede ry, so dit gaan die eerste 3 te slaan, en dan wil die tweede ding in die sin dat, so dit gaan hierdie een te kry. Maar dit is nog net 'n enkel-dimensionele skikking. En so, as ek wou om 'n wyser te wys dat die skikking, Ek sou sê int * p = x; Die tipe van x is net - Dit is ruwe gesê tipe van x, want dit is net 'n simbool en dit is nie 'n werklike veranderlike, maar dit is net 'n int *. x is net 'n wyser na die begin van hierdie. >> [Student] Goed. En daarom sal ek nie in staat wees om [1] [2] om toegang te verkry tot. Ek dink daar is 'n spesiale sintaksis vir die verklaring van 'n wyser, iets belaglik soos int (* p [- iets absoluut belaglik Ek het nie eens weet nie. Maar daar is 'n sintaksis vir die verwysings soos met hakies en dinge te verklaar. Dit kan selfs nie toelaat dat jy dit doen. Ek kon terugkyk op iets wat jou sal vertel my die waarheid. Ek sal kyk vir dit later, indien daar is 'n sintaksis vir punt. Maar jy sal nooit dit sien. En selfs die sintaksis is so argaïes dat as jy dit gebruik, sal mense met stomheid geslaan word. Multidimensionele skikkings is redelik skaars soos dit is. Jy pretty much - Wel, as jy doen matriks dinge dit is nie van plan te wees skaars, maar in C wat jy selde gaan die gebruik van multidimensionele skikkings. Ja. >> [Student] Kom ons sê jy het 'n baie lang skikking. In virtuele geheue dit sou blyk te wees alle opeenvolgende, soos die elemente wat reg langs mekaar, maar in die fisiese geheue, sou dit moontlik wees vir wat verdeel word? >> Ja. Hoe virtuele geheue werk is dit skei net - Die eenheid van die toekenning is 'n bladsy, wat geneig is om 4 kilogrepe, en so wanneer 'n proses, sê, hey, ek wil hierdie geheue te gebruik, die bedryfstelsel gaan dit 4 kilogrepe vir daardie klein blok geheue te ken. Selfs as jy net 'n enkele klein byte in die hele blok van die geheue, die bedryfstelsel gaan gee dit die volle 4 kilogrepe. So wat dit beteken is ek kon het - laat ons sê dit is my stapel. Hierdie stapel geskei kan word. My stapel kan wees megagrepe en megagrepe. My stapel kan groot wees. Maar die stapel self word verdeel in afsonderlike bladsye, wat as ons kyk na hier kom ons sê dit is ons RAM, as ek het 2 GB RAM, dit is 'n werklike adres 0 soos die nulde greep van my RAM, en dit is 2 GB al die pad af hier. So hierdie bladsy kan hier stem ooreen met hierdie blok. Hierdie bladsy kan stem ooreen met hierdie blok hier. Hierdie een mag stem ooreen met hierdie een hier. So die bedryfstelsel is gratis fisiese geheue te wys aan enige individuele bladsy arbitrêr. En dit beteken dat indien hierdie grens gebeur om 'n skikking te straddle, 'n skikking gebeur te word van hierdie links en regs van die einde van 'n bladsy, dan is dat die skikking word in fisiese geheue verdeel gaan word. En dan wanneer jy die program afsluit, wanneer die proses eindig, hierdie afbeeldings kry skoongemaak, en dan is dit vry om hierdie klein blokke te gebruik vir ander dinge. Nog vrae? [Student] Die wyser rekenkunde. >> O ja. Strings was makliker, maar kyk na iets soos ints, so terug na int x [4]; Of dit nou 'n skikking of dit is 'n wyser na 'n malloced verskeidenheid van 4 heelgetalle, dit gaan op dieselfde manier behandel word. [Student] So skikkings is op die hoop? [Bowden] Skikkings is nie op die hoop. >> [Student] Oh. [Bowden] Hierdie tipe van 'n skikking is geneig om te wees op die stapel tensy jy verklaar dit op globale veranderlikes te ignoreer. Globale veranderlikes gebruik nie. Binnekant van 'n funksie wat ek sê int x [4]; Dit gaan 'n 4-integer blok op die stapel te skep vir hierdie skikking. Maar dit malloc (4 * sizeof (int)); gaan om te gaan op die wal. Maar na hierdie punt wat ek kan gebruik X en P in pretty much dieselfde maniere, behalwe die uitsonderings wat ek het gesê voor oor wat jy kan toewys p. Tegnies, hulle groottes is ietwat anders, maar dit is heeltemal irrelevant. Jy het nog nooit eintlik hulle groottes. Die p ek kon sê p [3] = 2 of x [3] = 2; Jy kan gebruik om hulle in presies dieselfde manier. So pointer rekenkundige nou - Ja. [Student] Het jy nie p * te doen as jy die hakies? Die hakies is 'n implisiete dereference. >> Goed. Eintlik, ook wat jy sê met die kan jy multidimensionele skikkings met wysers, wat jy kan doen, is iets soos, laat ons sê, int ** pp = malloc (sizeof (int *) * 5); Ek sal net skryf dit alles uit die eerste. Ek wou nie dat 'n mens. Okay. Wat ek hier gedoen het is - Dit moet pp [i]. So pp is 'n verwysing na 'n wyser. Jy mallocing pp om te verwys na 'n verskeidenheid van 5 int sterre. So jy het in die geheue op die stapel pp. Dit gaan om te verwys na 'n verskeidenheid van 5 blokke wat almal hulself wysers. En dan wanneer ek malloc af hier, ek malloc dat elk van die individuele verwysings moet verwys na 'n afsonderlike blok van 4 grepe op die hoop. So hierdie punte tot 4 grepe. En hierdie een punte na 'n ander 4 grepe. En almal van hulle aan hul eie 4 bytes. Dit gee my 'n manier van die multidimensionele dinge te doen. Ek kon sê pp [3] [4], maar nou is dit nie dieselfde ding as multidimensionele skikkings omdat multidimensionele skikkings vertaal [3] [4] in 'n enkele verreken in die x-skikking. Hierdie dereferences p, toegang tot die derde indeks, dan dereferences dat en toegange - 4 ongeldig sou wees - die tweede indeks. AANGESIEN dat toe ons die int x [3] [4] voor as 'n multi-dimensionele skikking en wanneer jy dubbel bracket dit is regtig net 'n enkele dereference, jy na 'n enkele wyser en dan 'n offset, hierdie is regtig 2D verwysings. Jy volg 2 aparte wenke. So het dit ook tegnies kan jy multidimensionele skikkings te hê waar elke individu skikking is verskillende groottes. So ek dink kronkelende multidimensionele skikkings is wat dit genoem word sedert die eerste ding wat werklik kan verwys na iets wat 10 elemente, die tweede ding kan verwys na iets wat 100 elemente. [Student] Is daar 'n beperking op die aantal van die wenke wat jy kan hê wys aan ander wenke? >> No. Jy kan int ***** p. Terug na pointer rekenkundige - >> [student] Oh. >> Ja. [Student] As ek int *** p en dan doen ek 'n ontwysing en Ek sê p * is gelyk aan hierdie waarde, is dit net 1 vlak van ontwysing te doen? >> Ja. So as ek wil om toegang te verkry tot die ding wat die laaste wyser wys - Dan doen jy *** p. >> Goed. So, dit is p punte tot 1 blok, punte na 'n ander blok, punte na 'n ander blok. Dan as jy dit doen * p = iets anders, dan is jy is besig om te verander hierdie nou verwys na 'n ander blok. >> Goed. [Bowden] En as hierdie malloced, dan is jy het nou geheue gelek tensy jy gebeur verskillende verwysings van hierdie want jy kan nie terug te kry vir diegene wat wat jy net weggegooi. Pointer rekenkunde. int x [4]; gaan om 'n verskeidenheid van 4 heelgetalle te ken waar x gaan om te verwys na die begin van die skikking. So as ek sê iets soos x [1], ek wil gaan na die tweede heelgetal in die skikking te beteken, wat sou hierdie een wees. Maar regtig, dit is 4 grepe in die skikking aangesien hierdie heelgetal neem 4 bytes. So 'n afset van 1 beteken regtig 'n afset van 1 keer die grootte van ongeag die tipe van die skikking is. Dit is 'n verskeidenheid van heelgetalle, so dit weet 1 keer grootte van die int te doen wanneer dit wil verreken. Die ander sintaksis. Onthou dat dit gelykstaande aan * (x + 1); Toe ek sê wyser + 1, wat opbrengste is die adres wat die wyser in die stoor plus 1 keer die grootte van die tipe van die wyser. So as x = ox100, dan is x + 1 = ox104. En jy kan misbruik en iets sê soos: char * c = (char *) x; en nou C is gaan na dieselfde adres as x wees. c gaan wees gelyk aan ox100, maar c + 1 gaan wees gelyk aan ox101 sedert pointer rekenkundige hang af van die tipe van die wyser wat jy toe te voeg tot. So c + 1, dit lyk op c, dit is 'n char pointer, so dit gaan 1 keer grootte van char by te voeg, wat altyd gaan wees 1, so jy kry 101, terwyl as ek doen x, wat ook nog 100, x + 1 gaan wees 104. [Student] Kan jy maak gebruik van C + + om jou muis te bevorder deur 1? Ja, jy kan. Jy nie kan doen met x want x is net 'n simbool, dit is 'n konstante, jy nie kan verander x. Maar c gebeur net 'n wyser, sodat c + + is volkome geldig en dit sal deur 1 inkrementeer. As c net 'n int *, dan is c + + 104 word. + + Nie wyser rekenkundige net soos c + 1 sou hê pointer rekenkundige gedoen. Dit is eintlik hoe 'n baie van die dinge soos merge soort - In plaas van die skep van kopieë van dinge, kan jy plaas slaag - Soos as ek wou om die helfte van die skikking te slaag - laat sommige van hierdie vee. Kom ons sê ek wou hierdie kant van die skikking te slaag in 'n funksie. Wat sou ek slaag om daardie funksie? As ek slaag x, ek verby hierdie adres. Maar ek wil hierdie spesifieke adres te slaag. So, wat moet ek slaag? [Student] Pointer + 2? [Bowden] So x + 2. Ja. Wat gaan om hierdie adres te wees. Jy sal dikwels sien dit ook as x [2] en dan die adres van daardie. So wat jy nodig het om die adres te neem omdat die bracket is 'n implisiete dereference. x [2] verwys na die waarde wat in hierdie boks, en dan sal jy wil hê dat die adres van daardie boks, sodat jy sê & x [2]. So dit is hoe iets in merge soort waar jy wil hê dat die helfte van die lys na iets om te slaag jy regtig net slaag & x [2], en nou so ver as die rekursiewe oproep betrokke is, my nuwe skikking begin daar. Laaste minuut vrae. [Student] As ons nie 'n ampersand of 'n - wat is dit genoem? >> Star? [Student] Star. >> Tegnies, dereference operateur, maar - >> [student] Dereference. As ons nie 'n ster of 'n ampersand sit, wat gebeur as ek net y sê = x en x is 'n wyser? Wat is die tipe van y? >> [Student] Ek sal net sê dit is wyser 2. So as jy net sê y = x, nou x-en y-punt aan die dieselfde ding. >> [Student] Point aan die dieselfde ding. En as x is 'n int wyser? >> Dit sou kla want jy kan nie wysers wys. [Student] Goed. Onthou dat verwysings, alhoewel ons trek hulle soos pyle, regtig alles wat hulle winkel - int * x - regtig alle x stoor is iets soos ox100, wat ons gebeur te stel as wys na die blok gestoor word op 100. So wanneer ek sê int * y = x; ek net die kopiëring van ox100 in y, wat ons net gaan voor te stel as y, ook verwys na ox100. En as Ek sê int i = (int) x; dan sal ek gaan om te slaan wat die waarde van ox100 is binnekant van dit, maar nou is dit gaan vertolk word as 'n heelgetal in plaas van 'n wyser. Maar jy moet die cast of anders sal dit kla. [Student] So bedoel jy om te gooi - Gaan dit beslissende int van x of beslissende int van y? [Bowden] Wat? [Student] Goed. Na hierdie hakies is daar gaan 'n x of ay daar? [Bowden] nie. x en y is ekwivalent. >> [Student] Goed. Want hulle is albei wysers. >> Ja. [Student] So dit sou die stoor van die heksadesimale 100 in heelgetal vorm? >> [Bowden] Ja. Maar dit is nie die waarde van wat dit ookal wys na. [Bowden] Ja. >> [Student] Dus net die adres in heelgetal vorm. Okay. [Bowden] As jy wou vir sommige vreemd rede, jy kan uitsluitlik met wysers en nooit gaan met heelgetalle en net soos int * x = 0. Dan is jy gaan om te kry regtig verward wanneer wyser rekenkundige begin gebeur. So het die getalle wat hulle slaan is betekenisloos. Dit is net hoe jy beland hulle interpretasie. Dus is ek vry ox100 te kopieer van 'n int * na 'n int, en ek is vry om te wys jy's waarskynlik gaan om te skree nie vir die beslissende - Ek is vry om te wys iets soos (int *) ox1234 in hierdie arbitrêre int *. So ox123 is net so geldig 'n geheue adres & y. & Y gebeur iets wat pretty much ox123 om terug te keer. [Student] Sou dit werklik 'n koel manier om te gaan van heksadesimaal desimale vorm, soos as jy 'n wyser en jy gooi dit as 'n int? [Bowden] Jy kan regtig net print soos printf gebruik. Kom ons sê ek het int y = 100. So printf (% d \ n - as jy reeds behoort te weet - druk as 'n heelgetal,% x. Ons sal net druk dit as heksadesimale. So 'n wyser is nie gestoor as heksadesimaal, en 'n heelgetal is nie gestoor as desimale. Alles wat gestoor word as binêre. Dit is net dat ons geneig is wenke om te wys as heksadesimale omdat ons dink dat van die dinge wat in hierdie 4-byte blokke, en geheue adresse is geneig om vertroud te wees. Ons is soos, as dit begin met bf, dan is dit gebeur om te wees op die stapel. So dit is net ons interpretasie van wysers as heksadesimale. Okay. Enige laaste vrae? Ek sal hier wees vir 'n bietjie na as jy enigiets anders. En dit is die einde van daardie. [Student] Yay! [Applous] [CS50.TV]