[Powered by Google Translate] [Oddiel 4 - Viac Komfortné] [Rob Bowden - Harvard University] [To je CS50. - CS50.TV] Máme kvíz zajtra, v prípade, že vy nevedel, že. Je to v podstate na všetko, čo ste mohli vidieť v triede alebo mali vidieť v triede. To zahŕňa ukazovatele, aj keď sú veľmi nedávnej tému. Tie sa aspoň pochopiť vysokej úrovne z nich. Čokoľvek, čo bol preč cez v triede, mali by ste pochopiť, pre kvíz. Takže ak máte nejaké otázky na nich, môžete požiadať je teraz. Ale to bude veľmi študent-viedol zasadnutie, kde ste klásť otázky, takže dúfajme, že ľudia majú otázky. Má niekto nejaké otázky? Áno. >> [Študent] Môžeš ísť cez ukazovateľov znova? Pôjdem cez ukazovateľov. Všetky vaše premenných nutne žiť v pamäti, ale zvyčajne nemusíte báť, že a stačí povedať x + 2 a y + 3 a kompilátor bude zistiť, kde veci sú živé na vás. Akonáhle máte čo do činenia s ukazovateľmi, teraz si explicitne pomocou týchto adresy pamäte. Takže jediné premenné iba niekedy žiť v jednom adresu v danom okamihu. Ak chceme deklarovať ukazovateľ, čo sa typu bude vyzerať? Chcem vyhlásiť ukazovateľ p Čo typu vyzerať? [Študent] int * p Jo >>. Takže int * p A ako mám urobiť to poukázať na x? >> [Študent] Ampersand. [Bowden] Tak ampersand je doslova nazýva adresa prevádzkovateľa. Takže keď hovorím, a x je to stále na pamäti adresu premennej x. Takže teraz mám ukazovateľ p, a kdekoľvek v mojom kóde môžem použiť * p alebo by som mohol použiť x a bude to presne to isté. (* P). Čo je to robíš? Čo, že hviezda znamená? [Študent] To znamená, že hodnota v tomto bode. Jo >>. Takže keď sa pozrieme na to, môže to byť veľmi užitočné upozorniť na diagramy ak je to krabička pamäte pre x, ktoré sa stane, že na hodnotu 4, potom máme malú krabičku pamäte pre p, a tak p ukazuje na x, takže sme nakresliť šípku z bodu P do x. Takže keď hovoríme, * p hovoríme ísť do poľa, ktoré je p Hviezda je sledovať šípku a potom robiť, čo chcete s týmto box tu. Takže môžem povedať, * p = 7, a že pôjde na pole, ktoré je x, a zmeny, ktoré sa 7. Alebo by som mohol povedať, int z = * p * 2; To mätúce, pretože je to hviezda, hviezda. Jedna hviezda je dereferencing p, druhý hviezda vynásobením 2. Všimnite si, by som mohol mať rovnako dobre nahradil * p s x. Môžete ich použiť rovnakým spôsobom. A potom o niečo neskôr I môže mať p bod na úplne novú vec. Môžem len povedať, p = &z; Takže teraz p už neodkazuje na x, ale poukazuje na z. A kedykoľvek som to * p je to rovnaké, ako robí z Takže užitočná vec na tom je, akonáhle začneme dostať do funkcií. Je to trochu zbytočné deklarovať ukazovateľ, ktorý ukazuje na niečo, čo a potom ste len dereferencing to keď ste mohol použiť pôvodnú premennú začať. Ale keď sa dostanete do funkcií - tak povedzme, že máme nejakú funkciu, int foo, ktorý berie ukazovateľ a len robí * P = 6; Rovnako ako sme videli predtým, než sa swapu, môžete to urobiť efektívne swap a samostatnú funkciu tým, že len okolo celých čísel, pretože všetko v C je vždy okolo hodnoty. Aj keď ste okolo ukazovatele ste okolo hodnoty. To len tak sa stane, že tieto hodnoty sú adresy pamäte. Takže keď hovorím foo (p), som okolo ukazovateľ do funkcie foo a potom foo robí * p = 6; Takže v tejto funkcie, * p je stále ekvivalentná x, ale nemôžem použiť x vnútri tejto funkcie, pretože to nie je rozsahom v tejto funkcii. Takže * p = 6 je jediný spôsob, ako môžem získať prístup k miestnej premennej z inej funkcie. Alebo, no, ukazovatele sú jediný spôsob, ako môžem získať prístup k miestnej premennej z inej funkcie. [Študent] Povedzme, že ste sa chceli vrátiť ukazovateľ. Ako presne to robíte, že? [Bowden] Vracia ukazovateľ ako v niečo ako int y = 3; return & y? >> [Študent] Jo. [Bowden] Dobre. Nikdy by ste nemali urobiť. To je zlé. Myslím, že som videl v týchto prednáškových snímok si začal vidieť celý tento diagram pamäte kde tu máte pamäťovú adresu 0 a tu máte adresu v pamäti 4 koncerty alebo 2 na 32. Takže máš nejaké veci a nejaké veci a potom sa budete musieť váš stack a máte svoj haldy, ktoré ste práve začal poznávať, rastie. [Študent] Nie haldy nad zásobníka? Jo. Halda je na vrchole, je to tak? >> [Študent] No, dal 0 na vrchole. [Študent] Oh, dal 0 na vrchole. >> [Študent] Oh, dobre. Upozornenie: Kdekoľvek s CS50 budete vidieť, že týmto spôsobom. >> [Študent] Dobre. Je to len, že keď ste najprv vidieť stohy, ako keď si myslíte, že stoh si myslíte, že stohovanie veci na vrchole jedného iný. Takže máme tendenciu otočiť to asi tak stack rastie ako stack normálne miesto zásobníka visí dole. >> [Študent] Ešte nie hromady technicky rastú až príliš, aj keď? Záleží na tom, čo máte na mysli tým, vyrastať. Zásobník a halda vždy rastú v opačných smeroch. Zásobník je vždy vyrastá v tom zmysle, že je to rastie k vyššej pamäťovej adresy, a haldy rastie dole v tom, že je to stále k nižším adresy pamäte. Takže vrchol je 0 a dno je vysoká adresy pamäte. Sú obaja rastie, len v protiľahlých smeroch. [Študent] Len som myslel, že preto, že ste povedal, že ste dal hromadu na dne pretože sa zdá viac intuitívne, pretože pre zásobník začať na vrchole haldy, haldy je na vrchole seba taky, takže to je - >> Jo. Môžete tiež myslieť na hromadu ako vyrastať a väčšie, ale zásobník viac. Takže stack je ten, že sme trochu chcieť ukázať rastie. Ale všade, kam sa pozriete inak sa chystá ukázať adresu 0 hore a najvyšší adresa pamäte v dolnej časti, takže to je váš obvyklý pohľad na pamäti. Máte otázku? [Študent] Môžete nám povedať viac o hromadu? Jo. Aj k tomu sa dostaneme za chvíľu. Po prvé, ísť späť, prečo vracať & Y je zlá vec, na zásobníku budete mať veľa zásobníka snímok, ktoré reprezentujú všetky funkcie ktoré boli povolaní. Takže ignorovať predchádzajúce veci, horná časť zásobníka je vždy bude hlavné funkcie pretože to je to prvá funkcia, ktorá je volaná. A potom, keď budete volať inú funkciu, zásobník porastie dole. Takže keď ti budem hovoriť nejakú funkciu, foo, a to má svoj vlastný zásobník rám, môže volať nejakú funkciu, bar, to dostane jeho vlastné zásobníka rám. A bar môže byť rekurzívne, a to mohol zavolať sám, a tak, aby druhý hovor do baru bude mať svoje vlastné zásobníka rám. A tak, čo sa deje v týchto stack rámy sú všetky lokálne premenné a všetky argumenty funkcie, ktoré - Všetky veci, ktoré sú lokálne rozsahom tejto funkcii pokračovať v týchto zásobníku rámov. Takže to znamená, že keď som povedal niečo ako bar je funkcia, Idem len vyhlásiť celé číslo a vráti ukazovateľ na tento integer. Tak kde y žijú? [Študent] y žije v bare. >> [Bowden] Jo. Niekde v tomto malom námestí pamäte je štvorec littler, ktorý má y v ňom. Keď som sa vrátiť a y, vraciam ukazovateľ na tento malý blok pamäte. Ale potom, keď funkcia vracia, jeho stack frame dostane vyskočila zo zásobníka. A to je dôvod, prečo sa tomu hovorí stack. Je to ako štruktúry zásobníka dát, ak viete, čo to je. Alebo dokonca ako hromada zásobníkov je vždy príkladom, Hlavné je ísť na dne, potom prvá funkcia voláte sa ísť na vrchole, že a môžete sa dostať späť do hlavného, ​​až sa vrátite zo všetkých funkcií, ktoré boli tzv , Ktoré boli umiestnené na vrchole toho. [Študent] Takže ak ste to vrátiť a y, že hodnota sa môžu zmeniť bez predchádzajúceho upozornenia. Áno, to - >> [Študent] Mohlo by to byť prepísané. Jo >>. Je to úplne - Ak sa pokúsite - To by tiež int * bar, pretože sa vracia ukazovateľ, tak jeho návratový typ je int *. Ak sa pokúsite použiť návratovú hodnotu tejto funkcie, je to nedefinované správanie preto, že ukazovateľ ukazuje na zlú spomienkou. >> [Študent] Dobre. Takže čo keď, napríklad, ste vyhlásil int * y = malloc (sizeof (int))? To je lepšie. Áno. [Študent] Hovorili sme o tom, ako keď sme pretiahnuť veci do nášho koša oni nie sú v skutočnosti odstránené, sme len stratiť ich ukazovatele. Takže v tomto prípade sa budeme vlastne vymazať hodnotu, alebo je tam ešte v pamäti? Z väčšej časti, bude to ešte bude. Ale povedzme, že náhodou zavolať nejakú inú funkciu, Baz. Baz dostane svoj vlastný zásobník rám tu. Je to bude prepísanie všetkých týchto vecí, a potom, ak sa neskôr vyskúšať a používať ukazovateľ, ktorý ste dostali skôr, to nebude mať rovnakú hodnotu. Bude to zmenilo len preto, že ste volal funkciu Baz. [Študent] Ale už nie sme, stále by sme si 3? [Bowden] S najväčšou pravdepodobnosťou, že nie. Ale nemôžete spoľahnúť na to. C len hovorí, nedefinované správanie. [Študent] Oh, to robí. Dobre. Takže keď sa chcete vrátiť ukazovateľ, to je miesto, kde malloc prichádza v prevádzke. Píšem vlastne len návrat malloc (3 * sizeof (int)). Pôjdeme cez malloc viac sekundu, ale predstava, že malloc je všetko vaše lokálnych premenných vždy ísť na stack. Čokoľvek, čo sa malloced pokračuje na halde, a to navždy a vždy na halde kým je výslovne uvoľniť ju. Takže to znamená, že keď malloc niečo, bude to prežiť po funkcia vráti. [Študent] Bude to prežiť po programu sa zastaví? >> Nie Dobre, takže to tam bude, kým program je predovšetkým spôsob, ako urobiť chodu. Áno >>. Môžeme ísť cez detaily o tom, čo sa stane, keď sa program zastaví. Možno budete musieť pripomínať mňa, ale to je samostatná vec úplne. [Študent] Tak malloc vytvára ukazovateľ? Jo >>. Malloc - >> [Študent] Myslím, že malloc označuje blok pamäti, že ukazovateľ môže použiť. [Bowden] Chcem, aby diagram znovu. >> [Študent] Takže táto funkcia funguje, aj keď? [Študent] Jo, malloc označuje blok pamäte, ktoré môžete použiť, a potom sa vráti adresu prvého bloku tejto pamäte. [Bowden] Jo. Takže, keď malloc, ste chytil nejaký blok pamäte že je v súčasnej dobe v halde. Ak Halda je príliš malý, potom haldy je len porastie, a to rastie v tomto smere. Takže povedzme, že haldy je príliš malý. Potom je to o rast trochu a vráti ukazovateľ na tento blok, ktorý práve vyrástol. Keď veci zadarmo, robíš väčší priestor v halde, takže potom neskôr nazvali malloc môžete znovu použiť, že pamäť, ktorú predtým uvoľnený. Dôležitá vec, o malloc a free je, že vám dáva úplnú kontrolu po celú dobu životnosti týchto pamäťových blokov. Globálne premenné sú vždy živý. Lokálne premenné sú nažive do ich pôsobnosti. Akonáhle idete okolo ortézy kučeravé, miestne premenné sú mŕtvi. Malloced pamäť je nažive, keď chcete, aby to bolo nažive a potom sa uvoľní, keď poviete, že môžu byť prepustený. To sú vlastne len 3 druhy pamäte, naozaj. Tam je automatická správa pamäte, čo je zásobník. Veci sa dejú za vás automaticky. Keď sa povie int x, je pamäť pridelená pre int x. Keď x dostane mimo rozsah, je pamäť kultivovaný pre x. Potom je tu dynamická správa pamäte, ktorá je čo malloc je, čo je, keď máte kontrolu. Môžete dynamicky rozhodnúť, kedy by mali pamäť a nemali by byť pridelené. A potom je tu statická, čo jednoducho znamená, že to žije večne, čo je to, čo globálne premenné. Sú to len vždy v pamäti. Otázky? [Študent] Môžete definovať blok len pomocou zložené zátvorky ale nemal by mať v prípade straty alebo while alebo niečo také? Môžete definovať blok ako vo funkcii, ale že má zložené zátvorky taky. [Študent] Takže nemôžete jednoducho ako náhodné dvojice zložených zátvoriek v kóde ktoré majú lokálne premenné? >> Áno, môžete. Vnútri int bare by sme mohli mať {int y = 3;}. Že to má byť tu. Ale to kompletne definuje rozsah int y. Po tomto druhom rovnátka kučeravé, môžete y nesmú byť naďalej používať. Skoro si to nikdy neurobil, hoci. Dostať sa späť na to, čo sa stane, keď program skončí, je to niečo ako rozšírený omyl / polovica lži, že dávame, aby sa len robiť veci lepšie. Povieme vám, že keď sa alokovať pamäť ste vyčleňujú kus RAM pre dané premenné. Ale ty si naozaj priamo dotýkať RAM niekedy vo svojich programoch. Ak si myslíte, že o tom, ako som kreslil - A skutočne, ak si prejsť v GDB uvidíte to isté. Bez ohľadu na to, koľkokrát si spustiť program alebo aký program používate, zásobník je vždy začať - ste vždy uvidí premenné okolo niečoho adresu oxbffff. Je to zvyčajne niekde v tejto oblasti. Ale ako môže 2 programy mohol mať ukazovatele na rovnakej pamäti? [Študent] Tam je nejaký ľubovoľný určenia, kde je oxbfff mal byť na RAM , Ktoré môžu byť v skutočnosti v rôznych miestach v závislosti na tom, kedy bola volaná funkcia. Jo. Termín je virtuálna pamäť. Myšlienka je, že každý jednotlivý proces, každý program, ktorý je spustený na počítači má vlastné - predpokladajme, že 32 bitov - úplne nezávislý adresový priestor. To je adresový priestor. Má svoje vlastné úplne nezávislé 4 GB na použitie. Takže, ak sa dostanete 2 programy súčasne, tento program vidí 4 GB k sebe, tento program vidí 4 GB k sebe, a to je nemožné pre tento program dereferencia ukazovatele a skončiť s pamäťou z tohto programu. A čo virtuálna pamäť je mapovanie z procesov adresového priestoru na skutočné veci na pamäti. Takže je to pre váš operačný systém, aby vedeli, hej, keď ten chlap dereferences ukazovateľ oxbfff, že v skutočnosti znamená že chce RAM byte 1000, vzhľadom k tomu, ak tento program dereferences oxbfff, že naozaj chce RAM byte 10000. Môžu byť ľubovoľne ďaleko od seba. To platí dokonca aj vecí v rámci jedného procesov adresného priestoru. Tak ako to vidia všetky 4 GB k sebe, ale povedzme, že - [Študent] Má každý proces - Povedzme, že máte počítač iba s 4 GB pamäte RAM. Má každý proces vidieť celé 4 GB? Áno >>. Ale 4 GB to vidí je lož. Je to jednoducho, že si myslí, že má všetky tieto pamäte, pretože nevie, iný proces existuje. To bude používať iba toľko pamäte, ako to vlastne potrebuje. Operačný systém sa nebude dať RAM do tohto procesu či to nebol použitý žiadny pamäť celého tohto regiónu. Nebude to, aby to pamäť pre túto oblasť. Ale nápad je to - ja sa snažím myslieť na - ja si nemyslím, že analógia. Analógie sú tvrdé. Jednou z otázok, virtuálnej pamäte alebo jedna z vecí, je to riešenie je to, že proces by mal byť úplne vedomí seba. A tak si môžete zapísať ľubovoľný program, ktorý len dereferences žiadny ukazovateľ, Páči stačí napísať program, ktorý hovorí, že * (ox1234), a to je to, dereferencing adresa pamäte 1234. Ale je to až do operačného systému a potom preložiť, čo znamená 1234. Takže ak 1234 sa stane, že platné adresa pamäte pre tento proces, ako je to na fronte, alebo tak niečo, potom to vráti hodnotu tejto pamäťovej adresy pokiaľ ide o proces vie. Ale ak 1234 nie je platná adresa, rovnako ako sa to stane pristáť v nejakom malom kúsku pamäti tu, ktorý je mimo zásobníka a za hromadu a vy ste naozaj používať, potom to je, keď sa dostanete veci, ako segfault chýb preto, že ste sa dotknete pamäti, že by ste nemali dotýkať. To je tiež pravda - 32-bit systém, 32 bitov znamená, že máte 32 bitov pri definovaní adresu pamäte. Je to dôvod, prečo ukazovatele sú 8 bytov, pretože 32 bitov je 8 bytov - alebo 4 bajty. Ukazovatele sú 4 byty. Takže keď vidíte ukazovateľ, ako oxbfffff, že je - V akomkoľvek programe stačí postaviť ľubovoľnú ukazovateľ, kdekoľvek od ox0 do volské 8 f 's - FFFFFFFF. [Študent] Nevravel si, že sú 4 byty? Jo >>. [Študent] Potom každý byte bude mať - >> [Bowden] Hexadecimálny. Hexadecimálne - 5, 6, 7, 8. Takže ukazovateľmi budete vždy vidieť v šestnástkovej sústave. Je to len, ako delíme ukazovatele. Každé 2 číslice šestnástkovej je 1 byte. Takže tam to bude 8 hexadecimálnych číslic pre 4 byty. Takže každý ukazovateľ na 32-bitovom systéme bude 4 byty, čo znamená, že vo vašom procese môžete postaviť ľubovoľného 4 bajty a aby ukazovateľ z toho, , Čo znamená, že ak je to známe, môže to riešiť celý 2 až 32 bajtov pamäte. Aj keď to naozaj nie je prístup k že, aj keď je počítač má iba 512 MB, si myslí, že má toľko pamäte. A operačný systém je dosť šikovný na to, že to bude len pridelí to, čo skutočne potrebujete. To nie je len tak, oh, nový proces: 4 koncerty. Jo. >> [Študent] Čo vôl znamená? Prečo si to napísal? Je to len symbol na hexadecimálne. Keď vidíte číslo začiatok s volom, postupné veci sú hexadecimálne. [Študent] si vysvetľoval, čo sa stane, keď program skončí. Áno >>. Čo sa stane, keď program skončí, je operačný systém len vymaže mapovanie, že má pre tieto adresy, a to je to. Operačný systém môže teraz len dať tú spomienku na iný program používať. [Študent] Dobre. Takže keď budete prideľovať niečo na halde alebo zásobníka alebo globálne premenné alebo niečo, všetci len tak zmiznúť, akonáhle program skončí pretože operačný systém je teraz zadarmo, aby sa pamäť iných procesov. [Študent] I keď tam sú pravdepodobne stále hodnoty písané v? Jo >>. Hodnoty sú pravdepodobne stále existujú. Je to jednoducho, že to bude ťažké dostať sa na ne. Je to oveľa ťažšie dostať sa na ne, než je dostať sa na zmazaného súboru pretože zmazaný súbor druh sedí tam po dlhú dobu, a pevný disk je oveľa väčší. Takže to bude prepisovať rôzne časti pamäte pred tým, než sa stane prepísať kus pamäti, že súbor používa k byť. Ale hlavnej pamäte, RAM, môžete prechádzať oveľa rýchlejšie, takže to bude veľmi rýchlo byť prepísané. Otázky týkajúce sa tejto alebo čokoľvek iné? [Študent] Mám otázky týkajúce sa inej témy. Dobre >>. Má niekto nejaké otázky na túto tému? Dobre. Iná téma. >> [Študent] Dobre. Chcel som cez niektoré z praktických testov, a v jednom z nich sa hovorilo o sizeof a hodnota, ktorá sa vracia, alebo rôzne typy premenných. Áno >>. A povedal, že obaja int a dlho obe vrátiť 4, takže obaja sú dĺžke 4 bajty. Je nejaký rozdiel medzi int a dlhé, alebo je to to isté? Áno, tam je rozdiel. C štandard - Ja som asi ísť pokaziť. C štandard je presne to, čo C je oficiálna dokumentácia C. To je to, čo hovorí. Takže C štandard len hovorí, že char bude navždy a vždy 1 bajt. Všetko po tom - krátky, je vždy len definovaný ako väčšie alebo rovné znak. Toto by mohlo byť prísne väčší ako, ale nie je pozitívny. Int je práve definovaná ako väčšie alebo rovné krátky. A dlhá je práve definoval ako väčší alebo rovná int. A dlho dlho je väčší alebo rovný dlho. Takže jediné, čo C štandard definuje je relatívna usporiadanie všetkého. Skutočná veľkosť pamäti, že veci zaberajú je všeobecne až po realizáciu, ale je to celkom dobre definovaná v tomto bode. >> [Študent] Dobre. Takže šortky sú takmer vždy bude 2 bytov. Ints sú takmer vždy bude 4 byty. Dlhé dlhé výrobky sú takmer vždy bude 8 bytov. A túži, to záleží na tom, či používate 32-bit alebo 64-bit systém. Tak dlho bude zodpovedať typu systému. Ak používate 32-bitový systém ako Appliance, že to bude 4 byty. Ak používate 64-bit ako veľa novších počítačoch, to bude 8 bytov. Ints sú takmer vždy 4 bytov v tomto bode. Dlhé dlhé výrobky sú takmer vždy 8 bytov. V minulosti, ints používaný len 2 byty. Ale si všimnúť, že táto plne spĺňa všetky tieto vzťahov väčší ako a rovné. Tak dlho sa dokonale dovolené byť rovnakej veľkosti ako celé číslo, a je to tiež mohli byť rovnakej veľkosti ako long long. A to len tak náhodou, že v 99,999% systémov, sa bude rovnať buď int alebo long long. Záleží len na 32-bit alebo 64-bit. >> [Študent] Dobre. V pláva, ako je desatinné miesto určené v podmienkach kúskov? Rovnako ako ako binárny? Jo >>. Nemusíte vedieť, že pre CS50. Nemusíte ani dozvedieť, že v 61. Nemáte naučiť, že skutočne v každom predmete. Je to len charakter. Zabudol som presne bit prídely. Myšlienka s plávajúcou desatinnou čiarkou, je, že môžete alokovať určitý počet bitov reprezentovať - V podstate všetko, čo je vo vedeckej notácii. Takže si prideliť určitý počet bitov na reprezentáciu čísla sám, ako 1,2345. Nikdy predstavovať číslo s viac číslicami, ako 5. Potom sa tiež prideliť určitý počet bitov, takže má tendenciu byť ako môžete ísť len do určitej číslo, tak je najväčší exponent môžete mať, a môžete ísť len do určitej exponentom, rád, že je to najmenší exponent môžete mať. Nespomínam si presne spôsob, akým bity sú určené pre všetky z týchto hodnôt, ale určitý počet bitov sú venované 1,2345, ďalšie určitý počet bitov sú určené pre exponent, a je to len možné reprezentovať exponentu o určitej veľkosti. [Študent] A double? Je to ako extra dlhú plaváku? Jo >>. Je to to isté ako float, s výnimkou teraz používate 8 bajtov miesto 4 bajty. Teraz budete môcť používať 9 číslic alebo 10 číslic, a to bude môcť ísť do 300 namiesto 100. >> [Študent] Dobre. A plaváky sú tiež 4 byty. Áno >>. No, opäť, pravdepodobne záleží celkovo o všeobecné vykonávanie, ale plaváky sú 4 byty, dvojlôžkové sú 8. Zdvojnásobí sa nazývajú dvojitá, pretože sú dvakrát veľkosť plaváky. [Študent] Dobre. A sú tam double štvorhre? >> Nie sú. Myslím, že - >> [Študent] Ako dlhých túžia? Jo >>. To si nemyslím. Áno. [Študent] Na minuloročnej testu bola otázka o hlavnú funkciu musel byť súčasťou vášho programu. Odpoveď bola, že to nemusí byť súčasťou vášho programu. V akej situácii? To je to, čo som videl. [Bowden] Zdá sa, že - >> [Študent] Akú situáciu? Máte problém? >> [Študent] Jo, môžem rozhodne vytiahnite ju. To nemusí byť, technicky, ale v podstate to bude. [Študent] Videl som jeden na iné roku. Bolo to ako True alebo False: platná - >> Oh, c súbor.? . [Študent] Každý c súbor musí mať - [ako povedané naraz - nezrozumiteľný] Dobre. Tak to je samostatná. . C súbor iba musí obsahovať funkcie. Môžete zostaviť súbor do strojového kódu, binárne, bez ohľadu, aby bolo spustiteľný ešte. Platný spustiteľný, musí mať hlavnú funkciu. Môžete napísať 100 funkcie v 1 súbore, ale nie hlavné a potom skompilovať, ktoré sa na binárne, potom môžete napísať iný súbor, ktorý má len hlavné, ale to si vyžaduje veľa z týchto funkcií v tomto binárny súbor sem. A tak, keď robíš spustiteľný súbor, ktorý je čo linker robí je to kombinuje tieto 2 binárne súbory do spustiteľného. Tak. C súbor nemusí mať hlavnú funkciu vôbec. A na veľké bázou kódu uvidíte tisíce. Súbory C a 1 hlavného súboru. Ďalšie otázky? [Študent] Tam bol ďalšia otázka. To povedal, aby ich kompilátor. Pravda alebo lož? A odpoveď bola falošná, a pochopil som, prečo to nie je ako Clang. Ale čo hovoríme, aby, ak to nie je? Urobte je v podstate len - vidím presne to, čo hovorí. Ale to len spúšťa príkazy. Urobte. Môžem vytiahnuť toto hore. Jo. Oh, yeah. Skontrolujte tiež to robí. To hovorí, že účelom utilitou make je určiť automaticky ktoré časti veľkého programu sa musí prekompilovať a vydávať príkazy k prekompilovať. Môžete urobiť make súbory, ktoré sú úplne obrovská. Urobte pozerá na časové pečiatky súborov a ako sme povedali skôr, môžete zostaviť jednotlivé súbory dole, a nie je to až sa dostanete do linker že sú dohromady do spustiteľného súboru. Takže ak máte 10 rôznych súborov a vykonať zmenu na 1 z nich, potom to, čo urobiť, je robiť, je len prekompilovať, že 1 súbor a potom znova všetko dohromady. Ale je to oveľa hlúpejší než to. Je na vás, aby ste kompletne definovať, že je to to, čo by mala robiť. Je štandardne má schopnosť rozpoznať toto časovú pečiatku veci, ale môžete napísať make súbor nič robiť. Môžete napísať, aby súbor tak, že keď zadáte, aby to len cd do iného adresára. Bola som frustrovaná, pretože som pripináčika všetko vnútri môjho spotrebiče a potom som zobraziť PDF z Mac. Tak som ísť do Finder a môžem si ísť, Pripojiť k serveru, a server sa pripojiť k je môj spotrebiča, a potom som otvoriť PDF , Ktorý sa zostavuje LaTeXu. Ale ja som začínal byť frustrovaný, pretože zakaždým som potreboval obnoviť PDF, Musel som skopírovať ho do konkrétneho adresára, ktorý by mohol získať prístup a to bolo stále nepríjemné. Takže namiesto toho som napísal make súbor, ktorý budete musieť definovať, ako to robí veci. Ako urobíte v tomto je PDF LaTeX. Rovnako ako akúkoľvek inú značku súboru - alebo som asi ste nevideli Make súbory, ale máme v Appliance globálnej make súbor, ktorý práve hovorí, Ak sa kompilácie súbor C, použite rinčať. A tak tu v mojom súbore, ktorý na značku robím ja hovorím, Tento súbor budete chcieť kompilovať PDF LaTeXu. A tak je to PDF LaTeX, že to robí kompilácie. Urobte nie je kompilácie. Je to proste beží tieto príkazy v poradí som uviedol. Tak to beží PDF LaTeX, skopíruje ho do adresára chcem to byť skopírované, to cd do adresára a robí iné veci, ale všetko, čo robí, je uznať, keď súbor zmien, a ak zmení, potom to bude spustite príkazy, ktoré to má spustiť keď sa súbor zmení. >> [Študent] Dobre. Ja neviem, kde sa globálne Urobte súbory sú pre mňa pozrieť sa na to. Ďalšie otázky? Niečo z minulosti kvízy? Akékoľvek ukazovateľ veci? Existujú jemné veci, s ukazovateľmi, ako je - Nebudem mať možnosť nájsť kvízovú otázku na to - ale rovnako ako tieto veci. Uistite sa, že ste pochopili, že keď poviem, int * x * y - To nie je zrovna nič tu, myslím. Ale ako * x * y, ktoré sú 2 premenné, ktoré sú vo fronte. Keď poviem, že x = malloc (sizeof (int)), x je stále variabilný na zásobníku, malloc je nejaký blok nad v halde, a my máme x bod do haldy. Takže niečo na zásobníku ukazuje na hromadu. Kedykoľvek budete malloc niečo, ste nevyhnutne uložením vnútri ukazovateľ. Tak to je ukazovateľ na zásobníku, je malloced blok na halde. Mnoho ľudí si zmätený a povedať int * x = malloc, x je na hromadu. Nie, čo x poukazuje, je na halde. x sám je na stacku, ak z nejakého dôvodu ste x byť globálna premenná, v takom prípade sa stane, že je v inom regióne pamäti. Takže sledovanie, tieto krabice a šípka diagramy sú celkom bežné, že kvíz. Alebo, ak to nie je na kvíz 0, bude na teste 1. Mali by ste vedieť, všetky z nich, podľa krokov v zostavovaní pretože ste museli odpovedať na otázky týkajúce sa tých. Áno. [Študent] Mohli by sme vyraziť cez tieto kroky - >> Jasne. Pred krokov a zostavovaní sme predspracovanie, zostavovanie, montáž a prepojenie. Predspracovanie. Čo to má robiť? Je to najjednoduchší krok - dobre, nie ako - to neznamená, že by malo byť zrejmé, ale je to najjednoduchší krok. Vy mohli vykonávať to sami. Jo. [Študent] Vezmi si, čo máte vo vašej zahŕňa takto, a to kopíruje a potom tiež definuje. Vyzerá to na veci ako # include a # define, a to len kópie a pasty, čo skutočne znamenajú. Takže keď hovoríte # include cs50.h, preprocesor je kopírovanie a vkladanie cs50.h do tohto riadku. Keď sa povie # define x za 4, preprocesor prechádza celý program a nahrádza všetky výskyty x s 4. Takže preprocesor má platnú C súbor a výstupy platný C súbor kde veci boli skopírovať a vložiť. Takže teraz kompiláciu. Čo to má robiť? [Študent] To ide z C na binárne. [Bowden] To nie je ísť celú cestu na binárne. [Študent] do strojového kódu a potom? >> To nie je strojový kód. [Študent] zhromaždenia? >> Zhromaždenie. Ide to zhromaždenie, než prejde celú cestu ku kódu C, a väčšina jazykov niečo také. Vybrať akýkoľvek vysokej úrovni jazyka, a ak budete kompilovať, je pravdepodobné, zostaviť v krokoch. Najprv to bude kompilovať Python do C, potom to bude kompilovať C do zhromaždenia, a potom zhromaždenie sa chystá preložené do binárne. Takže kompilácie bude, aby ju z C na zhromaždení. Slovo zostavovaní zvyčajne znamená uviesť ho na vyššej úrovni na nižšej úrovni programovacieho jazyka. Tak to je len krok pri zostavovaní, kde môžete začať s high-úrovni jazyka a skončí v low-level jazyk, a to je dôvod, prečo je krok nazýva kompilácia. [Študent] Počas zostavovania, povedzme, že ste urobili # include cs50.h. Bude kompilátor rekompilaci cs50.h, rovnako ako funkcií, ktoré sú tam, a previesť do assembleri rovnako, alebo to bude skopírovať a vložiť niečo, čo bolo pre-zhromaždenie? cs50.h bude do značnej miery nikdy skončiť v zhromaždení. Veci ako funkcia prototypov a veci sú len pre vás byť opatrní. To zaručuje, že kompilátor môžete skontrolovať veci, ako ste volanie funkcií s právom návratové typy a správne argumenty a tak. Takže cs50.h bude predspracovanie do súboru, a potom, keď je to kompiláciu je to v podstate vyhodiť po dbá na to, aby všetko, čo je nazývané správne. Ale funkcie definované v CS50 knižnici, ktoré sú oddelené od cs50.h, ti nebudú samostatne zostavený. To bude skutočne zostúpi v prepojení kroku, takže k tomu sa dostaneme za chvíľu. Ale najprv, čo je montáž? [Študent] Montáž na binárne? Jo >>. Zostavenie. Nechceme hovoriť, že zostavovanie, pretože zhromaždenie je do značnej miery čistej preklad binárne. Tam je veľmi málo logiku ísť od zhromaždenia na binárne. Je to ako hľadať v tabuľke, oh, máme tento návod; ktorá zodpovedá binárne 01110. A tak sa súbory, ktoré montáž všeobecne výstupy sú. O súbory. A o Súbory sú to, čo sme hovorili skôr, Ako súbor nemusí mať hlavnú funkciu. Každý súbor môže byť zostavený až do. Súboru ° tak dlho, ako je to platný C súboru. To môže byť zostavený do. O.. Teraz, prepojenie je, čo vlastne prináša veľa. O súbory a prináša im spustiteľný. A tak to, čo robí, je linkovanie môžete myslieť na CS50 knižnice ako. Súbor °. Je to už skompilovaný binárny súbor. A tak pri kompilácii súboru, váš hello.c, ktorý volá GetString, hello.c dostane zostavujú do hello.o, hello.o je teraz v binárnom formáte. Používa GetString, tak to musí ísť cez k cs50.o, a linker smooshes dohromady a skopíruje GetString do tohto súboru a prichádza s spustiteľný súbor, ktorý má všetky funkcie, ktoré potrebuje. Takže cs50.o nie je vlastne O súbor, ale je to dosť blízko, že nie je žiadny podstatný rozdiel. Takže prepojenie práve prináša veľa súborov dohromady že samostatne obsahujú všetky funkcie je potrebné použiť a vytvára spustiteľný súbor, ktorý bude skutočne spustiť. A tak to aj to, čo sme hovorili pred kde môžete mať 1000. c súbory, kompilovať ich všetky. o súbory, ktorá bude pravdepodobne chvíľu trvať, potom zmeníte 1. c súboru. Jediné, čo potrebujete prekompilovať, že 1. C súbor a potom znova všetko ostatné, odkaz všetko dohromady. [Študent] Keď sme prepájanie píšeme lcs50? Jo, tak lcs50. Tá vlajka signály linker, ktorý by mal byť spájajúci v tejto knižnici. Otázky? Už sme prešli binárne iné ako tie, ktoré 5 sekúnd na prvej prednáške? To si nemyslím. Mali by ste vedieť, všetky veľké Os, že sme preč cez, a vy by ste mali byť schopní, keby sme vám dal funkciu, mali by ste byť schopní povedať, že je to veľký O, zhruba. Alebo dobre, veľký O je drsný. Takže ak ste vidieť vnorené cykly for smyčkování cez rovnaký počet vecí, ako int i, i > [Študent] n na druhú. >> To býva n na druhú. Ak ste triple vnorené, to inklinuje byť n Cubed. Takže tieto veci by ste mali byť schopní poukázať okamžite. Musíte vedieť, vloženie druh bubliny a radenie a zlúčiť druh a všetky z nich. Je to ľahšie pochopiť, prečo sú tie, n na druhú a n log n a všetky, ktoré pretože si myslím, že bol na teste jeden rok, ak sme v podstate vám dal vykonávanie bublinkové druhu a povedal: "Čo je doba chodu tejto funkcie?" Takže ak ste uznať, že ako bubliny radiť, potom môžete okamžite povedať, n na druhú. Ale ak ste na neho len pozrú, vy ani nemusíte uvedomiť, že je to bublina druhu; stačí povedať, je to robí toto a toto. Toto je n na druhú. [Študent] Existujú nejaké ťažké príklady môžete prísť s, ako podobné myšlienky prísť? Nemyslím si, že by sme vám žiadne nepríjemné príklady. Bublina sort vec je asi tak ťažké, ako by sme ísť, a dokonca aj to, že tak dlho, ako ste pochopili, že ste iterácie pole pre každý prvok v poli, ktorý sa bude niečo, čo sa n na druhú. Existujú všeobecné otázky, ako tu máme - Oh. Len druhý deň, Doug tvrdil, "som vymyslel algoritmus, ktorý je možné triediť pole "Zn čísel v O (log n) čas!" Tak ako môžeme vedieť, že to nie je možné? [Nepočuteľné Študent odpoveď] >> Jo. Prinajmenšom, budete musieť dotknúť každý prvok v poli, takže je možné triediť pole - Ak je všetko v poriadku netriedeného, ​​potom budete dotýkať všetko v poli, takže je možné to urobiť za menej než O n [Študent] Ukázal si nám, že príklad, že sú schopní to urobiť v O n ak používate veľké množstvo pamäte. Jo >>. A to je - ja zabudol, čo to je - je to počítanie druh? Hmm. To je celé číslo triedenie algoritmus. Hľadal som zvláštne mená pre to, že som si nemohol spomenúť minulý týždeň. Jo. Jedná sa o typy druhov, ktoré môžu docieliť veci vo veľkom O n Ale existujú obmedzenia, ako je možné použiť iba celé čísla do určité číslo. Plus, ak sa snažíte vyriešiť niečo to je - Ak váš pole je 012, -12, 151, 4000000, potom, že jeden prvok bude úplne zničiť celý triedenie. Otázky? [Študent] Ak máte rekurzívne funkciu, a to len robí rekurzívne volanie v rámci return, to je chvost rekurzívny, a tak by nebolo využívajú viac pamäte za behu , Alebo by aspoň používať porovnateľné pamäte ako opakujúce sa riešenie? [Bowden] Áno. Bolo by pravdepodobne trochu pomalší, ale nie tak celkom. Chvost rekurzívne je docela dobrý. Sa znovu pozrieme stack snímok, povedzme, že máme hlavné a máme int bar (int x), alebo tak niečo. To nie je dokonalý rekurzívne funkcie, ale návrat bar (x - 1). Tak samozrejme, toto je chybný. Musíte základné prípady a tak. Ale myšlienka je, že toto je chvost rekurzívny, čo znamená, že keď hlavné hovory bar to dostane jeho stack frame. V tomto zásobníku ráme to bude málo blok pamäte ktorá zodpovedá jeho argument x. A tak povedzme, že hlavné stane volať bar (100); Takže x bude začať ako 100. Ak kompilátor uznáva, že je to chvost rekurzívne funkcie, potom, keď bar robí jeho rekurzívne volanie bar, namiesto toho, aby sa nový zásobníka rám, ktorý je miesto, kde zásobník začne rastúce prevažne, nakoniec to bude prebiehať do haldy a potom dostanete segfault chýb pretože pamäť začína zrážať. Takže namiesto toho, aby svoj vlastný zásobník rám, môže si uvedomiť, hej, ja nikdy musieť vrátiť k tomuto rámca frontu, takže namiesto toho som si len vymeniť tento argument s 99 a potom začať bar po celom tele. A potom to bude robiť to znova a dosiahnu návrate bar (x - 1), a namiesto toho, aby nový rámec frontu, bude to len nahradenie súčasnej argument s 98 a potom skočiť späť na začiatku bare. Tieto operácie, ktoré je nahradí hodnotu 1 na zásobníku a skákanie späť na začiatok, sú celkom účinné. Takže je nielen to isté využitie pamäte ako samostatná funkcia, ktorá je interaktívne preto, že ste iba pomocou 1 zásobníka frame, ale nie ste utrpenie nevýhody mať volanie funkcií. Volanie funkcie môže byť trochu drahé, pretože má toto všetko nastavenie a teardown a všetky tieto veci. Tak toto chvost rekurzia je dobrá. [Študent] Prečo to nevytvára nové kroky? Vzhľadom k tomu, že si uvedomuje, že nie je potrebné. Výzva k baru je len vracia rekurzívneho volania. Takže to nemusí robiť nič s návratovú hodnotu. Je to len tak, aby okamžite vrátiť. Tak to len tak nahradiť jeho vlastné argumentácii a začať znovu. A tiež, ak nemáte chvost rekurzívne verzii, potom dostanete všetky tieto bary, kde, kedy tento ukazovateľ vracia má vrátiť jeho hodnotu na tento jeden, a potom, že bar sa okamžite vráti a vráti jeho hodnotu na tento jeden, potom je to len tak, aby sa ihneď vrátiť a vráti jeho hodnotu na tento jeden. Takže šetríte to objavovať všetky tieto veci preč zásobníka pretože vrátená hodnota je len tak, aby sa preniesla celú cestu späť rovnako. Tak prečo nie len vymeniť náš argument s aktualizovaným argumentu a začať znovu? Ak funkcia nie je chvost rekurzívny, ak robíte niečo ako - [Študent], pokiaľ bar (x + 1). Jo >>. Takže ak ste to v stave, potom robíte niečo s návratovú hodnotu. Alebo aj keď ste práve urobiť návrat 2 * bar (x - 1). Takže teraz bar (x - 1) musí vrátiť, aby sa pre výpočet 2 krát, že hodnoty, takže teraz to potrebujú svoj samostatný zásobník rám, a teraz, bez ohľadu na to, ako veľmi sa snažíš, budete musieť - To nie je chvost rekurzívne. [Študent] Chcel som skúsiť priviesť rekurziu usilovať o koncovej rekurzia - [Bowden] V ideálnom svete, ale v CS50 nemusíte sa. S cieľom získať rekurzia chvosta, všeobecne, môžete nastaviť ďalší argument kde bar bude mať int x do y a y zodpovedá konečnému vec, ktorú chcete vrátiť. Takže potom budete vracať bar (x - 1), 2 * y. Takže je to len na vysokej úrovni, ako transformovať veci boli chvost rekurzívne. Ale navyše argument - A potom na konci, keď sa dostanete na základné prípad, stačí sa vrátiť y pretože ste sa hromadia po celú dobu návratovú hodnotu, ktorú chcete. Tak nejako si to robím iteratívne, ale pomocou rekurzívne volanie. Otázky? [Študent] Možno o ukazovateľ aritmetický, rovnako ako pri použití reťazca. Iste >>. Ukazovateľ aritmetika. Pri použití reťazcov je to ľahké, pretože reťazce sú char hviezdy, znaky sú navždy a vždy jeden byte, a tak ukazovateľ aritmetické je ekvivalentná k pravidelnému aritmetiky, keď máte čo do činenia s reťazcami. Povedzme, že char * s = "hello". Takže máme blok v pamäti. Treba 6 bajtov, pretože sa vždy potrebujete null terminátor. A char * s sa bude poukázať na začiatku tohto poľa. Takže s bodmi tam. Teraz, to je v podstate, ako každý pole funguje, bez ohľadu na to, či bol návrat do malloc alebo či je to na zásobníku. Každá rada je v podstate ukazovateľ na začiatok poľa, a potom každý pole operácie, akékoľvek indexovanie, je len tak do tohto poľa určité vyrovnanie. Takže keď som povedal niečo ako s [3], čo bude s a počítanie 3 znaky a Tak s [3], máme 0, 1, 2, 3, takže s [3] sa bude vo vzťahu k tomuto l [Študent] A tak by sme mohli dosiahnuť rovnakú hodnotu tým, že robí S + 3 a potom zátvorky star? Áno. To je ekvivalentná * (s + 3); a že je navždy a vždy ekvivalentné bez ohľadu na to, čo robíte. Už nikdy nebudete musieť použiť držiak syntax. Môžete vždy použiť * (y + 3) syntax. Ľudia majú tendenciu rád držiaku syntax, hoci. [Študent] Takže všetky polia sú vlastne len ukazovatele. Tam je nepatrný rozdiel, keď poviem, int x [4]; >> [Študent] Znamená to, že vytvoriť pamäť? [Bowden] To bude vytvárať 4 ints vo fronte, tak 16 bytov celkovo. Bude to vytvoriť 16 bajtov na zásobníku. x nie je uložené kdekoľvek. Je to len symbol odkazuje na začiatku vec. Pretože ste vyhlásila, pole vnútri tejto funkcie, čo kompilátor urobí je len nahradiť všetky výskyty premennej x tam, kde sa to stalo zvoliť, aby týchto 16 bajtov. Je možné to urobiť s char * s, pretože s je skutočný ukazovateľ. Je zadarmo ku prejdite na iné veci. x je konštantná. Nemožno mať miesto na inom poli. >> [Študent] Dobre. Ale táto myšlienka, toto indexovanie, je rovnaká bez ohľadu na to, či je to tradičné pole alebo či je to ukazovateľ na niečo alebo či je to ukazovateľ na malloced poľa. A v skutočnosti, že je tak ekvivalentná, že je tiež jedno a to isté. Je to vlastne len znamená, čo je vo vnútri hranatých zátvoriek a to, čo zostalo z držiakov, je spočíta, a dereferences. Tak toto je rovnako platný ako * (y + 3), alebo s [3]. [Študent] Môžete mať ukazovatele ukazujúce na 2-rozmerné pole? Je to ťažšie. Tradične, no. 2-rozmerné pole je len 1-rozmerné pole s nejakou pohodlnú syntax pretože keď poviem, int x [3] [3], je to naozaj len 1 pole s 9 hodnotami. A tak keď som index, kompilátor vie, čo mám na mysli. Keď poviem, že x [1] [2], že vie, že chcem ísť do druhej rady, takže to bude preskočiť prvé 3, a potom to chce druhý vec, takže to bude stáhni jeden. Ale je to stále len jedno-rozmerné pole. A tak keď som chcel priradiť ukazovateľ na danom poli, Povedal by som, že int * p = x; Typ x je len - Je to drsné hovoriť typ x, pretože je to len symbol, a to nie je skutočné premenné, ale je to len int *. x je len ukazovateľ na začiatok tohto. >> [Študent] Dobre. A tak nebudem mať prístup [1] [2]. Myslím, že je zvláštne Syntax pre deklarovania ukazovatele, niečo smiešne ako int (* p [-. niečo úplne smiešne Ja ani neviem. Ale je tu Syntax pre deklarovania ukazovatele, ako so zátvorkami a vecí. Dokonca sa ani nemusí nechať urobiť. Som sa mohol pozrieť späť na niečo, čo by mi pravdu. Pozriem sa na to neskôr, ak je syntax pre bod. Ale nikdy nebudete vidieť. A dokonca aj syntax je tak archaický, že ak budete používať, budú ľudia zmätene. Viacrozmerné polia sú veľmi zriedkavé, ako to je. Ste celkom veľa - No, ak robíte veci, matice to nebude vzácne, ale v C budete len zriedka bude používať viacrozmerné polia. Jo. >> [Študent] Povedzme, že máte naozaj dlhú poľa. Takže vo virtuálnej pamäti, že sa zdá byť všetko po sebe idúcich, ako prvky priamo vedľa seba, ale vo fyzickom pamäti, že by bolo možné, že sa nie je možné deliť? Áno >>. Ako virtuálna pamäť funguje, je to len oddeľuje - Jednotka pridelenie je stránka, ktorá má tendenciu byť 4 KB, a tak keď proces hovorí, hej, ja chcem použiť túto pamäť, operačný systém bude pridelí mu 4 kB pre toho malého bloku pamäte. Dokonca aj keď si len použiť jeden malý byte v celom bloku pamäti, operačný systém sa bude dať mu plné 4 KB. Takže to, čo to znamená, je, že som mohol mať - povedzme, že to je moja stack. Tento zásobník môže byť oddelený. Môj stack môže byť megabajtov a megabajty. Môj stack môže byť obrovský. Ale stack sám má byť rozdelený do jednotlivých stránok, ktorá, ak sa pozrieme na tu povedzme, že to je naša RAM, keď mám 2 GB pamäte RAM, je to skutočná adresa 0 ako 0. byte môjho RAM, a to je 2 GB všetky tu dole. Takže táto stránka môže zodpovedať tomuto bloku sem. Táto stránka môže zodpovedať tomuto bloku sem. To by sa dalo odpovedať tento sem. Takže operačný systém je zadarmo priradiť fyzickej pamäte na jednotlivú stránku ľubovoľne. A to znamená, že ak sa táto hranica sa stane rozkročiť pole, poľa sa stane byť opustené to a právo tohto poradia stránky, potom toto pole sa bude rozdelená do fyzickej pamäte. A potom sa po ukončení programu, kedy proces skončí, Tieto mapovania sa vymažú a potom je to zadarmo využívať tieto malé bloky pre ostatné veci. Ďalšie otázky? [Študent] Ukazovateľ aritmetika. >> Ach jo. Reťazce bolo jednoduchšie, ale pri pohľade na niečo ako ints, tak späť do int x [4]; Či už je to pole, alebo či je to ukazovateľ na malloced pole celých čísel 4, to bude zaobchádzať rovnakým spôsobom. [Študent] Tak polia sú na halde? [Bowden] Pole nie sú na halde. >> [Študent] Oh. [Bowden] Tento typ poľa má tendenciu byť na zásobníku ak ste vyhlásil ju za - ignoruje globálne premenné. Nepoužívajte globálne premenné. Vnútri funkcie hovorím int x [4]; To bude vytvárať 4-celé číslo bloku na zásobníku pre toto pole. Ale to malloc (4 * sizeof (int)); sa chystá ísť na halde. Ale po tomto bode môžem použiť X a P v takmer rovnakým spôsobom, iné ako výnimiek, ktoré som povedal skôr, než o tom môžete priradiť ks. Technicky, ich veľkosti sú trochu odlišné, ale to je úplne irelevantné. Nikdy ste vlastne používajú svoje veľkosti. P Mohol by som povedať, p [3] = 2, alebo x [3] = 2; Môžete ich použiť v presne rovnakým spôsobom. Takže ukazovateľ aritmetika teraz - Áno. [Študent] Páči sa vám nemusel robiť p * ak máte držiaky? Konzoly sú implicitné dereferencia. Dobre >>. Vlastne, aj to, čo hovoríte, sa môžete dostať viacrozmerných polí s ukazovateľmi, čo môžete urobiť, je niečo ako, povedzme, int ** pp = malloc (sizeof (int *) * 5); Ja si len napísať to všetko ako prvý. Nechcela som, že jeden. Dobre. Čo som urobil, je tu - To by malo byť pp [i]. Takže pp je ukazovateľ na ukazovateľ. Ste mallocing pb poukázať na pole 5 hviezdičiek int. Takže v pamäti máte na zásobníku pp Bude to poukázať na pole 5 blokov, ktoré sú všetko sami ukazovatele. A potom, keď som malloc tu dole, som malloc, že ​​každý z týchto jednotlivých ukazovateľov by mala smerovať na samostatnom bloku 4 bajtov na zhromaždení. Takže tento poukazuje na 4 bajty. A tento ukazuje na odlišný 4 bajty. A všetky z nich poukazujú na ich vlastné 4 byty. To mi dáva spôsob, ako robiť multidimenzionálne veci. Mohol by som povedať, pp [3] [4], ale teraz to nie je to isté ako multidimenzionálne pole pretože viacrozmerné pole je preložená [3] [4] do jedinej posun do poľa x. Tento dereferences p, pristupuje tretí index, potom dereferences, že a prístupy - 4 by neplatné - druhý index. Vzhľadom k tomu, kedy sme mali int x [3] [4] ako pred, tak viacrozmerné pole a pri poklepaní držiak je to naozaj len jeden dereferencia, ste po jedinej ukazovateľ a potom offset, je to naozaj 2D odkazy. Môžete sledovať 2 samostatné ukazovatele. Tak to aj technicky umožňuje mať multidimenzionálne poľa kde každý jednotlivec je pole rôzne veľkosti. Takže si myslím, zubaté viacrozmerných polí je to, čo sa volá pretože naozaj prvá vec, ktorú by mohol smerovať k niečomu, čo má 10 prvkov, Druhá vec by mohol smerovať k niečomu, čo má 100 prvkov. [Študent] Je nejaký limit na počet ukazovateľov môžete mať ukázal na iné ukazovatele? >> Nie Môžete mať int ***** v. Späť na ukazovateľ aritmetiky - >> [študentka] Oh. Jo >>. [Študent] Ak mám int *** p a potom som urobiť dereferencing a hovorím p * je rovná tejto hodnote, je to len bude robiť 1 úroveň dereferencing? Áno >>. Takže keď chcem získať prístup k veci, že posledný ukazovateľ ukazuje na - Potom si urobiť *** p Dobre >>. Tak toto je p poukazuje na 1 blok, poukazuje na iného bloku, poukazuje na iného bloku. Potom, ak to urobíte * p = niečo iné, potom meníte to Doteraz poukázať na iný blok. Dobre >>. [Bowden] A ak boli malloced, potom ste teraz unikli pamäte ak sa stalo, že majú rôzne odkazy na tieto pretože sa nemôžete dostať späť k tým tie, ktoré ste práve zahodil. Ukazovateľ aritmetika. int x [4], sa bude alokovať pole celých čísel 4 kde x bude ukazovať na začiatku poľa. Takže keď som povedal niečo ako x [1], ja chcem, aby to znamená ísť do druhej celé číslo v poli, ktorý by bol tento. Ale naozaj, to je 4 bytov do poľa, pretože to číslo zaberá 4 bajty. Takže posun 1 naozaj znamená posun 1 krát väčšie ako bez ohľadu na typ poľa je. To je pole celých čísel, takže vie, ako urobiť 1 krát veľkosť int, keď sa chce vyrovnať. Iné syntaxe. Pamätajte si, že to je ekvivalentná * (x + 1); Keď poviem, že kurzora + 1, čo to vracia je adresa ukazovateľ je ukladanie plus 1 krát väčšiu typu ukazovateľ. Takže ak x = ox100, potom x + 1 = ox104. A môžete zneužívajú a povie niečo ako char * c = (char *) x; a teraz c bude rovnaká adresa ako x. c bude rovná ox100, ale c + 1 bude rovná ox101 od ukazovateľ aritmetický závisí od typu ukazovatele, ktoré sú pridané k Takže c + 1, to vyzerá na c, je to char ukazovateľ, takže to bude pridať 1 krát veľkosť char, , Ktorá sa vždy bude 1, takže budete mať 101, vzhľadom k tomu, keď to urobím x, ktorá je tiež stále 100, x + 1 bude 104. [Študent] Môžete použiť c + +, aby sa pokročilo ukazovateľ o 1? Áno, môžete. Môžete to urobiť s x, pretože x je len symbol, je to konštanta, nemôžete zmeniť x. Ale c sa stane byť len ukazovateľ, takže c + + je dokonale platné, a to bude zvyšovať o 1. Ak je c bolo len int *, potom c + + by sa 104. + + So ukazovateľ aritmetický rovnako ako c + 1 by mal urobiť ukazovateľ aritmetiku. To je vlastne, ako veľa vecí, ako je druh korešpondencie - Namiesto vytvárania kópií vecí, môžete namiesto toho prejsť - Rovnako ako keď som chcel, aby túto polovicu poľa - nechajte sa vymazať niečo z toho. Povedzme, že som chcel, aby túto stranu poľa do funkcie. Čo by som prejsť na túto funkciu? Ak prejdem x, som absolvovaní adresu. Ale ja chcem, aby túto konkrétnu adresu. Tak čo by som mal prejsť? [Študent] Pointer + 2? [Bowden] Tak x + 2. Áno. To ich bude táto adresa. Budete tiež veľmi často vidí to ako x [2], a potom adresu toho. Takže budete musieť vziať adresu, pretože držiak je implicitná dereferencia. x [2] sa vzťahuje na hodnotu, ktorá je v tomto poli, a potom sa má adresu tohto poľa, takže hovoríte & x [2]. Tak to je, ako sa niečo v druhu korešpondencie, kde chcete odovzdať polovicu zoznamu k niečomu naozaj len prejsť a x [2], a teraz až rekurzívne volanie sa týka, moje nové pole začína tam. Last minute otázky. [Študent] Ak sa nám nepodarí dať ampersand alebo - čo je to volá? >> Star? [Študent] Star. Technicky >>, dereferencia operátor, ale - >> [študentka] dereferencia. Ak nemáme dať hviezdu alebo ampersand, čo sa stane, keď som len povedať, y = x, a x je ukazovateľ? Aký je typ y? >> [Študent] Ja si len povedať, že je ukazovateľ 2. Takže ak ste práve povedal y = x, x a y teraz ukazujú na rovnakú vec. >> [Študent] Bod na rovnakú vec. A ak je x int ukazovateľ? >> To by si sťažovať, že nie je možné priradiť ukazovatele. [Študent] Dobre. Pamätajte si, že ukazovatele, aj keď sme kresliť ako šípy, Naozaj všetko, čo store - int * x - naozaj všetko x je ukladanie je niečo ako ox100, ktorý sa stane reprezentovať ako smerujúca k bloku uložené na 100. Takže keď hovorím int * y = x; som len kopírovanie ox100 do y, ktoré sme práve bude reprezentovať ako y, tiež ukázal na ox100. A keď poviem, int i = (int) x, potom aj sa chystá uložiť bez ohľadu na hodnotu ox100 je vnútri nej, ale teraz to bude vykladať ako celé číslo namiesto ukazovatele. Ale budete potrebovať sadru, alebo inde to bude sťažovať. [Študent] Tak to ste na mysli cast - Je to bude obsadenie int X aj liatie int na y? [Bowden] Čo? [Študent] Dobre. Po týchto zátvorkách je tam bude x, alebo ay tam? [Bowden] Buď. x a y sú rovnocenné. >> [Študent] Dobre. Vzhľadom k tomu, že sú obaja ukazovatele. Jo >>. [Študent] Tak to by uložiť hexadecimálne 100 v celej číslo forme? >> [Bowden] Jo. Ale nie hodnota bez ohľadu na to odkazuje. [Bowden] Jo. >> [Študent] Takže len adresa vo forme celého čísla. Dobre. [Bowden] Ak by ste chceli z nejakého dôvodu bizarné, môžete zaoberať výhradne s ukazovateľmi a nikdy riešiť s celými číslami a proste byť ako int * x = 0. Potom budete si naozaj zmätený, akonáhle ukazovateľ aritmetický začne deje. Takže čísla, ktoré ukladajú, sú nezmyselné. Je to len, ako ste skončili ich výklad. Takže som voľne kopírovať ox100 z int * na int, a ja som voľný priradiť - Si pravdepodobne bude dostať kričal na dobu odlievanie - Som voľná priradiť niečo ako (int *) ox1234 do tejto svojvoľné int *. Takže ox123 je rovnako platná adresa pamäte, ako je & y. A y sa stane vrátiť niečo, čo je celkom veľa ox123. [Študent] Bolo by to naozaj cool spôsob, ako ísť z šestnástkovej do desiatkovej podobe, ako keď máte ukazovateľ a obsadil ju ako int? [Bowden] Môžete naozaj len tlačiť pomocou ako printf. Povedzme, že mám int y = 100. Takže printf (% d \ n - ako by ste mali už viete - tlač, že ako celočíselné,% x. Budeme len vytlačiť ju ako hexadecimálne. Takže ukazovateľ nie je uložená ako hexadecimálne, a číslo nie je uložené ako desatinné. Všetko je uložené ako binárny. Je to len, že máme tendenciu ukázať ukazovatele ako hexadecimálne pretože si myslíme, že veci v týchto 4-byte blokoch, a pamäťové adresy majú tendenciu, aby sa zoznámili. My sme ako, keď začne s bf, potom sa stane, že je v zásobníku. Takže je to len naša interpretácia ukazovateľov ako hexadecimálne. Dobre. Nejaká posledné otázky? Budem tu na chvíľu po, ak máte niečo iné. A to je koniec, že. [Študent] Yay! [Potlesk] [CS50.TV]