[Powered by Google Translate] [Sekcio 4 - Pli Vasta] [Rob Bowden - Universitato Harvard] [Jen CS50. - CS50.TV] Ni havas kvizon morgaŭ, en la okazo you guys ne sciis tion. Estas esence pri ĉio vi povus esti viditaj en klaso aŭ devus esti vidita en klaso. Kiu inkludas punteros, kvankam ili estas tre freŝaj temo. Vi devus almenaŭ kompreni la altaj niveloj de ili. Ion, kio estis for super en klaso vi devus kompreni por la kvizo. Do se vi havas demandojn pri ili, vi povas peti ilin nun. Sed ĉi tiu tuj estos tre studento gvidata kunsido kie infanoj demandojn, tiel espereble homoj havas demandojn. Ĉu iu havas demandojn? Jes. >> [Studento] Ĉu vi povas iri super punteros denove? Mi tuj iros punteros. Ĉiuj viaj variabloj nepre vivos en memoro, sed kutime oni ne zorgu pri tio kaj vi simple diru x + 2 kaj y + 3 kaj la tradukilo elŝeligi kie la aĵoj vivas por vi. Iam vi pritraktas punteros, nun vi eksplicite uzante tiujn memoro adresoj. Do sola variablo nur iam vivi en unu sola adreso je ĉiu tempo. Se ni volas deklari pointer, kio estas la tipo iri al aspektas? Mi volas deklari puntero p. Kion faras la tipo aspektas? [Studento] int * p. >> Jes. Do int * p. Kaj kiel mi faru ĝin noti al x? >> [Studento] ampersand. [Bowden] Do signo laŭvorte nomis la adreson de operatoro. Do kiam mi diras & x Fariĝas la memoro adreso de la variablo x. Do nun mi havas la puntero p, kaj ie ajn en mia kodo mi povas uzi * p aŭ mi ne povis uzi x kaj estos la ĝusta sama afero. (* P). Kio estas ĉi faras? Kion tio stelo signifas? [Studento] Ĝi signifas valoro je tiu punkto. >> Jes. Do, se ni rigardas ĝin, ĝi povas esti tre utila al nudigos la diagramojn kie ĉi tiu estas iom skatolo da memoro por x, kio okazas al havi la valoro 4, tiam ni havis iom skatolo da memoro por p, kaj tiel p poentojn al x, do ni desegni sago de p al x. Do kiam ni diras * p ni dirante iri al la skatolo kiu estas p. Stelo estas sekvi la sago kaj do kion vi volas kun tiu skatolo dekstre tie. Do mi povas diri * p = 7, kaj kiu iros al la skatolo kiu estas x kaj ŝanĝo kiu al 7. Aŭ mi ne povis diri int z = * p * 2; Tio konfuzas ĉar la stelo, stelo. La stelo estas dereferencing p, la alia stelo estas multiplikante per 2. Rimarku mi povus havi same bone anstataŭis la * p kun x. Vi povas uzi ilin en la sama maniero. Kaj tiam poste mi povas havi p punkto al tute nova afero. Mi povas nur diri p = &z; Do nun p ne plu punktoj al x; notas al z. Kaj iam mi faros * p estas la sama kiel fari z. Do la utila afero pri ĉi tiu estas iam ni komencu akiri en funkcioj. Estas speco de senutile deklari puntero ke poentojn al io kaj tiam vi simple dereferencing ĝin kiam vi povus esti uzita la originala variablo por komenci. Sed kiam vi enir funkcioj - do ni diras, ke ni havas iun funkcion, int foo, kiu prenas puntero kaj nur faras * p = 6; Kiel ni vidis antaŭe kun interŝanĝa, vi ne povas fari efikan interŝanĝo kaj aparta funkcio por nur pasante entjeroj ĉar ĉiu en C estas ĉiam preteriras valoro. Eĉ kiam vi pasante punteros vi preterpasanta valoro. Simple tiel okazas ke tiuj valoroj estas memoro adresoj. Do kiam mi diras foo (p); Mi pasante la puntero en la funkcio foo kaj tiam foo faras * p = 6; Do ene de tiu funkcio, * p estas ankoraŭ ekvivalenta al x, sed mi ne povas uzi x ene de tiu funkcio, ĉar ĝi ne scoped ene de tiu funkcio. Do * p = 6 estas la sola maniero mi povas atingi lokan variablon de alia funkcio. Aŭ, nu, punteros estas la sola maniero mi povas atingi lokan variablon de alia funkcio. [Studento] Imagu ke vi volis reveni puntero. Kiel ekzakte vi faras tion? [Bowden] Reveno puntero kiel en iu kiel int y = 3; reveno & y? >> [Studento] Yeah. [Bowden] Okay. Vi devus neniam faros. Ĉi tiu estas malbona. Mi kredas ke mi vidis en tiuj prelego diapozitivoj vi komencis vidi tiun tutan diagramon de memoro kie ĝis tie vi havas memoron adreso 0 kaj cxi tie vi havas memoron adreso 4 koncertoj aŭ 2 al la 32. Tial vi havas iujn aferojn kaj iuj aĵoj kaj tiam vi havos vian stako kaj kiam vi mem havigis vian monteton, kiun vi ĵus eklernis pri, kreskis. [Studento] Ĉu ne la havaĵo super la pilo? Yeah. La amaso estas sur supro, ĉu ne? >> [Studento] Nu, li metis 0 sur. [Studento] Nu, li metis 0 sur. >> [Studento] Ho, bone. Disclaimer: Ie kun CS50 vi tuj vidos ĝin tiel. >> [Studento] Okay. Estas nur ke kiam vi unue vidante piloj, kiel kiam vi pensas pri pilo vi pensas pri staka vido aĵoj sur supro de unu alia. Do ni emas klaki ĉi ĉirkaŭe tiel la pilo kreskas supren kiel stako kutime would anstataŭ la pilo pendis malsupren. >> [Studento] Ne amasoj teknike kreski ankaŭ, kvankam? Ĝi dependas de kion vi volas diri per kreski. La pilo kaj amaso ĉiam kreski en kontraŭaj direktoj. Al pilo ĉiam kreski en la senco ke ĝi estas kreski al pli alta memoro adresoj, kaj la amaso kreskas malsupren en tiu ĝi estas kreskanta al suba memoro adresoj. Do la supro estas 0 kaj la fundo estas alta memoro adresoj. Ili ambaŭ kreski, ĝuste kontraŭaj direktoj. [Studento] Mi nur signifis ke ĉar vi diris ke vi metis stako sur la fundo ĉar ĝi similas pli intuicia ĉar por la pilo komenci ĉe la supro de monteto, amaso estas sur la supro de sin tro, do that's - >> Jes. Vi ankaŭ pensi pri la havaĵo kiel kreskis kaj pli grandaj, sed la pilo pli. Do la pilo estas kiu ni ia volas montri kreskis. Sed ĉie vi rigardas alie tuj montri adreso 0 je la supro kaj la plej alta memoro adreso malsupre, do ĉi tiu estas via kutima vidpunkto de memoro. Ĉu vi havas demandon? [Studento] Ĉu vi povas diri al ni pli pri la amaso? Yeah. Mi ricevos ke en sekundo. Unue, superante kial reveni & y estas malbona afero, sur la stako vi havas faskon da pilo kadroj kiuj reprezentas ĉiujn funkciojn kiuj estis nomata. Do ignorante antaŭa aĵoj, la supro de via pilo ĉiam tuj estos la ĉefa funkcio ĉar tio estas la unua funkcio ke tio esti nomita. Kaj kiam vi nomas alian funkcion, la stako tuj kreski malsupren. Do, se mi vokas iu funkcio, foo, kaj ricevas sian propran pilo kadro, ĝi povas nomi iujn funkcion, trinkejo; alvenas sian propran pilo kadro. Kaj trinkejo eblis rekursie kaj povus nomi sin, kaj por ke dua alvoko al trinkejo tuj akiri propran pilo kadro. Kaj tiel kion iras en tiuj pilo kadroj estas ĉiuj de la lokaj variabloj kaj ĉiuj de la funkcio argumentojn ke - Neniu tion, kio estas loke scoped al ĉi tiu funkcio iri en tiuj pilo kadroj. Do tio signifas, kiam mi diris ion kiel stango estas funkcio, Mi simple intencas deklari entjero kaj tiam revenu puntero al tiu entjero. Do kie ne y vivas? [Studento] y vivas en trinkejo. >> [Bowden] Yeah. Ie en tiu malgranda kvadrato de memoro estas malabunda kvadrata kiu havas y en ĝi. Kiam mi revenos & y, Mi revenis puntero al tiu malgranda bloko de memoro. Sed tiam kiam funkcio revenas, lia pilo kadro gets pusxis for la stako. Kaj tio estas kial ĝi estas nomata pilo. Estas kiel la pilo datumstrukturo, se vi scias, kio tio estas. Aŭ eĉ kiel stako de pletoj estas ĉiam la ekzemplo, ĉefa tuj iros sur la fundo, tiam la unua funkcio vi nomas tuj iros sur supro de tiu, kaj vi ne povas reiri al la ĉefa ĝis vi revenos el ĉiuj funkcioj, kiujn oni nomas kiuj estis metitaj sur supron. [Studento] Do se vi faris do redonas la & y, tiu valoro estas subjekto ŝanĝi sen averto. Jes, it's - >> [studento] Ĝi eblus anstataŭigi. >> Jes. Estas tute - Se vi provos kaj - Ĉi tio ankaŭ esti int * trinkejo ĉar ĝi estas reveni puntero, tial lia reveno tipo estas int *. Se vi provas uzi la reveno valoro de tiu funkcio, ĝi estas nedifinita konduto ĉar tio puntero notas al malbona memoro. >> [Studento] Okay. Do kio se, ekzemple, vi deklaris int * y = malloc (sizeof (int))? Tio estas bona. Jes. [Studento] Ni parolis pri kiel kiam ni treni aferojn al nia recicla bin ili ne efektive viŝita, ni nur perdos siajn punteros. Do en ĉi tiu kazo ni vere viŝi la valoro aŭ ĉu ankoraŭ en memoro? Plejparte, ĝi tuj ankoraŭ tie. Sed diru ni okazi nomi iu alia funkcio, baz. Baz tuj akiri propran pilo kadro ĉi tie. Oni tuj estos overwriting ĉio ĉi stuff, kaj poste, se vi poste provi kaj uzi la puntero ke vi havas antaŭe, ĝi ne tuj estos la sama valoro. Ĝi tuj ŝanĝiĝis nur ĉar vi nomas la funkcion baz. [Studento] Sed se ni ne, estus ankoraŭ get 3? [Bowden] Tre verŝajne vi volos. Sed vi ne povas fidi tion. C nur diras nedefinita konduto. [Studento] Ho, jes. Okay. Do, kiam vi volas reveni al puntero, ĉi tiu estas kie malloc venas en uzo. Mi skribas fakte ĝuste reveni malloc (3 * sizeof (int)). Ni transiru malloc pli en dua, sed la ideo de malloc estas ĉiuj viaj lokaj variabloj ĉiam iras sur la stako. Io ke tio malloced iras sur la havaĵon, kaj estos ĉiam kaj ĉiam esti sur la havaĵon ĝis vi eksplicite liberigi ĝin. Do tio signifas ke kiam vi malloc ion, tio okazas por postvivi post la funkcio redonas. [Studento] Ĉu ĝi postvivos post la programo haltas kurante? >> No Okay, do tuj estos tie ĝis la programo estas la tuta vojo farita kuri. >> Jes. Ni povas iri sur detalojn de kio okazas kiam la programo haltas kurante. Vi eble bezonas memorigi min, sed tio estas aparta afero tute. [Studento] Do malloc kreas puntero? >> Jes. Malloc - >> [studento] I think malloc designa blokon de memoro, ke puntero povas uzi. [Bowden] Mi volas, ke diagramon denove. >> [Studento] Do tiu funkcio laboras, kvankam? [Studento] Yeah, malloc designa blokon de memoro, ke vi povas uzi, kaj tiam redonas la adreson de la unua bloko de tiu memoro. [Bowden] Yeah. Do kiam vi malloc, vi kaptante iujn bloko de memoro jen nun en la havaĵo. Se la havaĵo estas tro malgranda, tiam la havaĵo estas ĝuste tuj kreski, kaj ĝi kreskas en tiu direkto. Do diru la havaĵo estas tro malgranda. Tiam temas pri kreski iom kaj resendas puntero al ĉi tiu bloko kiu ĝuste kreskis. Kiam vi liberan stuff, vi faris pli ĉambron en la havaĵo, do tiam poste nomi al malloc povas reuzi ke memoro kiun vi antaŭe estis liberigita. La grava afero pri malloc kaj libera estas kiu donas al vi kompletan kontrolon super la tuta vivo de tiuj memoro blokoj. Suma variabloj estas ĉiam vivas. Loka variabloj estas viva en sia amplekso. Tuj kiam vi iras preter unu frizita streĉa, la loka variabloj estas morta. Malloced memoro vivas kiam vi volas, ke li vivas kaj tiam estas liberigita kiam vi diras al tio kiel eldonita. Tiuj estas fakte la nur 3 tipojn de memoro, vere. Estas aŭtomata memoro demarŝon, kiu estas la pilo. Aĵoj okazas al vi aŭtomate. Kiam vi diras int x, memoro estas asignitaj por int x. Kiam x eliras de medio, memoro estas rekuperita por x. Tiam ekzistas dinamika memoro demarŝon, kiu estas kiu malloc estas, kio estas kiam vi havas kontrolon. Vi dinamike decidi kiam memoro devus kaj ne devas esti atribuitaj. Kaj tiam tie estas statika, kiu ĵus signifas ke ĝi vivas eterne, kiu estas kiu tutmonda variabloj estas. Ili estas nur ĉiam en la memoro. Demandoj? [Studento] Ĉu vi povas difini bloko nur uzante frizita krampoj sed ne devi havi se aserto aŭ dum deklaro aŭ io simila? Vi povas difini bloko kiel en funkcio, sed kiu havas frizita krampoj tro. [Studento] Do vi ne povas nur devas kiel hazarda paro de frizita krampoj en via kodo kiuj havas lokajn variablojn? >> Jes, vi povas. Ene de int trinkejo ni povus havi {int y = 3;}. Tio devus esti ĉi tie. Sed tio tute difinas la medio de int y. Post tiu dua frizita streĉa, y ne povas esti uzata plu. Vi preskaŭ neniam faras tion, though. Getting reen al kio okazas kiam programo finiĝas, ekzistas speco de miskompreno / duono mensogo, ke ni donu la celo nur fari aĵojn pli facila. Ni diras al vi ke kiam vi rezervi memoron vi atribuante iun eron de RAM por tiu variablo. Sed vi ne vere rekte tuŝi RAM eterna en viaj programoj. Se vi pensas pri tio, kiom mi tiris - Kaj efektive, se vi iras tra en GDB vi vidos la saman aferon. Sendepende de kiom fojoj vi kuras via programo aŭ kio programo ke vi uzas, la pilo estas ĉiam tuj komenci - vi ĉiam tuj vidos variabloj ĉirkaŭ adreso oxbffff ion. Estas kutime ie en tiu regiono. Sed kiel 2 programoj eble havas punteros al la sama memoro? [Studento] Jen iuj arbitraj indika kie oxbfff supozas esti sur la RAM kiu povas reale esti en malsamaj lokoj depende kiam la funkcio vokita. Yeah. La termino estas virtuala memoro. La ideo estas ke ĉiu unuopa procezo, ĉiu unuopa programo kiu ruliĝas sur via komputilo havas sian propran - ni supozu 32 bitoj - tute sendependa adreso spaco. Tio estas la adreso spaco. Ĝi havas sian propran tute sendependa 4 gigabajtoj uzi. Do se vi kuros 2 programoj samtempe, tiu programo vidas 4 gigabajtoj al sin, tiu programo vidas 4 gigabajtoj al sin, kaj estas neebla por tiu programo por dereference puntero kaj fini kun memoro de tiu programo. Kaj kion virtuala memoro estas estas surĵeto de procezoj adreso spaco al realaj aĵoj en RAM. Do ĝi estas ĝis via mastruma sistemo por scii ke, hey, kiam ĉi ulo dereferences puntero oxbfff, kiu vere signifas ke li volas RAM bajto 1000, dum se tiu programo dereferences oxbfff, li vere volas RAM bajto 10000. Ili povas esti arbitre malproksime aparte. Tio estas eĉ vera de aĵoj en sola procezoj adreso spaco. Do kiel li vidas ĉiujn 4 gigabajtoj al sin, sed diru - [Studento] Ĉu ĉiu unuopa procezo - Imagu ke vi havas komputilon kun nur 4 gigabajtoj de RAM. Ĉu ĉiu unuopa procezo vidi la tutan 4 gigabajtoj? >> Jes. Sed la 4 gigabajtoj vidas estas mensogo. Ĝi simple pensas ĝi havas ĉiujn ĉi memoro ĉar ĝi ne scias neniu alia procezo ekzistas. Ĝi estos nur uzi tiel memoro kiel ĝi vere bezonas. La mastruma sistemo ne tuj donu RAM al tiu procezo se ĝi ne uzas ajnan memoro en ĉi tiu tuta regiono. Oni ne tuj donos ĝin memoro por tiu regiono. Sed la ideo estas ke - mi provas pensi pri - mi ne povas pensi pri analogio. Analogioj estas malmola. Unu el la temoj de virtuala memoro aŭ unu el la aferoj ĝi estas solvanta estas ke procezoj devus esti tute ignoris unu la alian. Kaj tiel vi povas skribi ajnan programon kiu ĵus dereferences ajna pointer, kiel simple skribi programon kiu diras * (ox1234), kaj tiu estas dereferencing memoro adreso 1234. Sed estas ĝis la mastruma sistemo por poste traduki kion 1234 rimedoj. Do se 1234 okazas esti valida memoro adreso por ĉi procezo, kiel ĝi estas en la pilo aŭ io, tiam ĉi tiu redonos la valoron de tiu memoro adreso gxis la procezo scias. Sed se 1234 ne estas valida adreso, kiel okazas al la tero en iu malgranda peco de memoro tie estas preter la pilo kaj preter la amaso kaj vi ne vere uzis tiun, tiam tio estas kiam vi ricevas aĵojn kiel segfaults ĉar vi tuŝas memoro kiun vi ne devas esti tuŝi. Tio estas ankaŭ vera - Al 32-bita sistemo, 32 bitoj signifas ke vi havas 32 bitojn por difini memoro adreso. Estas kial punteros estas 8 bajtoj ĉar 32 bitoj estas 8 bajtoj - aŭ 4 bitokoj. Punteros estas 4 bitokoj. Do kiam vi vidas puntero kiel oxbfffff, tio estas - Ene ajna programo vi povas simple konstrui ajnan arbitran pointer, ie ajn el ox0 al bovo 8 f's - ffffffff. [Studento] Ĉu vi ne diras ili estas 4 bajtoj? >> Jes. [Studento] Tiam ĉiu bajto havos - >> [Bowden] Deksesuma. Deksesuma - 5, 6, 7, 8. Do punteros vi tuj ĉiam vidas en deksesuma. Estas nur ke ni klasifikas punteros. Ĉiu 2 ciferoj de deksesuma estas 1 bajtoj. Do tuj estos 8 deksesumaj ciferoj por 4 bitokoj. Do ĉiu unuopa puntero sur 32-bita sistemo tuj estos 4 bajtoj, kio signifas, ke en via procezo povas konstrui ajnan arbitran 4 bitokoj kaj fari puntero el ĝi, kio signifas, ke gxis estas konscia, ĝi povas trakti tutan 2 al la 32 bajtoj de memoro. Kvankam ĝi ne vere havas aliron al tiu, eĉ se via komputilo nur havas 512 megabajtojn, ĝi pensas ke ĝi havas tiom da memoro. Kaj la mastruma sistemo estas sufiĉe inteligenta, ke ĝi nur atribui kion vi fakte bezonas. Ĝi ne nur iru, ho, novan procezon: 4 koncertoj. Yeah. >> [Studento] Kion signifas la bovo signifas? Kial vi skribas tion? Estas nur la simbolo por deksesuma. Kiam vi vidos kelkajn komenco kun bovo, la pluaj aĵoj estas deksesuma. [Studento] Vi estis klarigante pri kio okazas kiam programo finiĝas. >> Jes. Kio okazas kiam programo finiĝas estas la mastruma sistemo nur viŝas la surĵetoj kiu havas por tiuj adresoj, kaj tio estas ĝi. La mastruma sistemo povas nun simple doni tiun memoron al alia programo por uzi. [Studento] Okay. Do kiam vi atribui iun sur la havaĵon aŭ la pilo aŭ tutmonda variabloj aŭ nenion, ili cxiuj nur malaperi tuj kiam la programo finiĝas ĉar la mastruma sistemo estas nun libera doni tiun memoron al ajna alia procezo. [Studento] Kvankam ne estas probable ankoraux valoroj skribita en? >> Jes. La valoroj estas verŝajna ankoraŭ tie. Oni ĵus tuj estos malfacile akiri ilin. Estas multe pli malfacile akiri ilin ol estas alveni al forviŝita dosieron ĉar la forviŝita dosiero specon de sidas tie dum longa tempo kaj la malmola disko estas multe pli granda. Do tuj anstatauxigas malsamaj partoj de memoro antaŭ ol ĝi okazas al anstataŭigi la bloko de memoro, ke tiu dosiero uzita por esti je. Sed ĉefmemoro, RAM, vi ciklo tra multe pli rapida, tiel okazas al tre rapide esti anstataŭigi. Demandoj pri tiu aŭ io alia? [Studento] Mi havas demandojn pri malsama temo. >> Bone. Ĉu iu havas demandojn pri tiu? Okay. Malsamaj temo. >> [Studento] Okay. Mi tuj tra iu el la praktiko provoj, kaj en unu el ili parolis pri la sizeof kaj la valoro kiu revenas aŭ malsama variablo tipoj. >> Jes. Kaj gxi diris ke ambaŭ int kaj longaj ambaŭ reveno 4, do ili estas ambaŭ 4 bitokoj longa. Ĉu estas diferenco inter int kaj longa, aŭ estas la sama afero? Jes, estas diferenco. La C normo - Mi verŝajne tuj salaton supren. La C normo estas ĝuste kiel kio C estas, la oficiala dokumentaro de C. Jen kion diras. Do la C normo ĵus diras ke char estos por ĉiam kaj ĉiam esti 1 bajto. Ĉio post tio - mallonga estas ĉiam nur difinita kiel estante pli granda ol aŭ egala al char. Tio povas esti strikte pli granda ol, sed ne pozitiva. An int estas simple difinita kiel estante pli granda ol aŭ egala al mallonga. Kaj longa estas nur difinita kiel estante pli granda ol aŭ egala al int. Kaj longa longa estas pli granda ol aŭ egala al longa. Do la sola afero la C normo difinas estas la relativa ordenamiento de ĉiu. La reala kvanto de memoro, ke aferoj levu estas ĝenerale ĝis efektivigo, sed ĝi estas sufiĉe bone difinitaj en ĉi tiu punkto. >> [Studento] Okay. Do mallongaj preskaŭ ĉiam tuj estos 2 bajtoj. Ints estas preskaŭ ĉiam tuj estos 4 bitokoj. Longa sopiras estas preskaŭ ĉiam tuj estos 8 bajtoj. Kaj sopiras, ĝi dependas de ĉu vi uzas de 32-bita aŭ 64-bita sistemo. Do longa tuj respondas al la tipo de sistemo. Se vi uzas 32-bitan sistemo kiel la Appliance, ĝi tuj estos 4 bitokoj. Se vi uzas 64-bita kiel multe da freŝaj komputiloj, ĝi tuj estos 8 bajtoj. Ints estas preskaŭ ĉiam 4 bitokoj je ĉi tiu punkto. Longa sopiras estas preskaŭ ĉiam 8 bajtoj. En la pasinteco, ints uzata por nur esti 2 bitokoj. Sed rimarki ke tiu tute kontentigas ĉiujn el tiuj rilatoj de pli granda ol kaj egala al. Tiel longe estas perfekte permesita al esti la sama amplekso kiel entjero, kaj ĝi estas ankaŭ permesita al esti la sama amplekso kiel longa longa. Kaj ĝuste tial hazarde estas, ke en 99,999% de sistemoj, tuj esti egala al ĉu int aŭ longa longa. Simple dependas de 32-bita aŭ 64-bita. >> [Studento] Okay. Per flosoj, kiom estas la dekuma punkto designado en terminoj de bitoj? Kvazaux duuma? >> Jes. Vi ne bezonas scii ke por CS50. Vi eĉ ne lernas, ke en 61. Vi ne lernas ke vere en ajna direkto. Estas nur reprezento. Mi forgesas la ĝusta iom allotments. La ideo de flosanta punkto estas ke vi rezervu specifa nombro de bitoj por reprezenti - Esence, ĉiu estas en scienca notacio. Do vi atribui specifan numeron da bitoj por reprezenti la nombro mem, kiel 1,2345. Mi neniam povas reprezenti nombro kun pli ol 5 ciferoj. Tiam vi ankaŭ rezervu specifa nombro de bitoj por ke ĝi emas esti kiel vi nur povas iru al certa nombro, kiel tio estas la plej granda eksponento vi povas havi, kaj vi nur povas iri en iun eksponento, kiel tio estas la plej malgranda eksponento povas havi. Mi ne memoras la ĝustan vojon bitoj estas atribuitaj al ĉiuj tiuj valoroj, sed iu numero de bitoj estas dediĉitaj al 1,2345, alia iun numeron de bitoj estas dediĉitaj al la eksponento, kaj estas nur ebla por reprezenti eksponento de iu grandeco. [Studento] Kaj duobla? Ĉu tio estas kiel ekstra longa kaleŝego? >> Jes. Ĝi estas la sama afero kiel kaleŝego krom nun vi uzas 8 bajtoj anstataŭ 4 bitokoj. Nun vi povos uzi 9 ciferoj aŭ 10 ciferoj, kaj ĉi povos iri ĝis 300 anstataŭ 100. >> [Studento] Okay. Kaj floto estas ankaŭ 4 bitokoj. >> Jes. Nu, denove, ĝi probable dependas entute sur ĝenerala apliko, sed flosas estas 4 bajtoj, duobloj estas 8. Duobloj nomas duobla ĉar ili estas duobla la grandeco de kaleŝegoj. [Studento] Okay. Kaj ili tie duoblan duobligas? >> Estas ne. Mi kredas - >> [studento] Kiel longe sopiras? >> Jes. Mi ne kredas tion. Jes. [Studento] La pasinta jaro provo estis demando pri la ĉefa funkcio devi esti parto de via programo. La respondo estis, ke ĝi ne devas esti parto de via programo. En kio situacio? Tion mi vidis. [Bowden] Sxajnas - >> [studento] Kio situacio? Ĉu vi havas la problemon? >> [Studento] Jes, mi povas definitive tiri gxin. Ĝi ne devas esti, teknike, sed esence tuj estos. [Studento] Mi vidis unu sur alian jaron. Estis kiel Vera aŭ Falsa: A valida - >> Ho, al. C dosiero? [Studento] Ajna. C dosiero devas havi - [ambaŭ parolantaj samtempe - nekomprenebla] Okay. Do jen disigas. A. C dosiero simple bezonas enhavi funkciojn. Vi povas kompili dosieron en maŝino kodo, duuma, kion ajn, sen ĝi esti ruleblan ankoraŭ. Entajpu validan ruleblan devas havi ĉefan funkcion. Vi povas skribi 100 funkcioj en 1 dosiero sed neniu ĉefa kaj poste kompilos ke malsupren al duuma, tiam vi skribos alia dosiero kiu nur havas ĉefan sed nomas aron da tiuj funkcioj en ĉi duuma dosiero super tie. Kaj tiel, kiam vi faras la ruleblan, jen kion la enlazador faras Estas ĝi kombinas tiuj 2 duumajn dosierojn en plenumeblan. Kaj la prezo. C dosiero ne bezonas havi ĉefan funkcion ajn. Kaj sur granda kodo bazoj vi vidos milojn da. C dosierojn kaj 1 ĉefa dosiero. Pli demandoj? [Studento] Ne estis alia demando. Ĝi diris fari estas tradukilo. Vera aŭ falsa? Kaj la respondo estis falsa, kaj mi komprenis kial ĝi ne estas kiel Clang. Sed kion ni nomas fari se ĝi ne estas? Faru estas esence nur - Mi povas vidi ĝuste kio ĝi nomas ĝin. Sed ĵus kuras ordonojn. Fari. Mi povas tiri tiun supren. Yeah. Ho, jes. Faru ankaux faras tion. Ĉi tio diras la celo de la fari utileco estas determini aŭtomate kio pecoj de granda programo bezonas esti recompiled kaj elsendi la komandojn recompilar ilin. Vi povas fari fari dosieroj kiuj estas absolute enorma. Faru rigardas la tempo poŝtmarkojn de dosieroj kaj, kiel ni diris antaŭe, vi povas kompili individuaj dosieroj malsupren, kaj ne estas ĝis vi atingos la enlazador ke ili estas kunmetita en plenumeblan. Do se vi havas 10 malsamajn dosierojn kaj vi fari ŝanĝon al 1 de ili, tiam kion fari tuj fari estas simple recompilar ke 1 dosiero kaj tiam relink ĉio kune. Sed estas multe dumber ol tio. Ĝi dependas de vi tute difinas ke tio kio devus esti farante. Ĝi defaŭlte havas la kapablon rekoni tiun tempon stampon stuff, sed vi povas skribi fari dosieron fari nenion. Vi povas skribi fari dosieron por ke kiam vi tajpas fari ĝin ĵus cd la alian dosierujon. Mi komencis frustritaj ĉar mi Tack ĉio ene de mia Appliance kaj tiam mi vidi la PDF de la Mac. Do mi iras al ranojn, kaj mi povas fari Iru Konekti al Servilo, kaj la servilo ligojn al mia Appliance, kaj tiam mi malfermi la PDF ke gets kompilita de LaTeX. Sed mi getting frustritaj ĉar ĉiu unuopa tempo mi bezonis por refreŝigi la PDF, Mi devis kopii ĝin al specifa dosierujo kiu ĝin povis konsenti kaj estis ĉiufoje ĝena. Do anstataŭe mi skribis fari dosieron, kiun vi havas al difini kiel faras tion. Kiel vi faras en ĉi estas PDF LaTeX. Same kiel ĉiu alia fari dosieron - aŭ mi supozas vi ne vidis la fakto dosieroj, sed ni havas en la Appliance tutmonda fari dosieron kiu nur diras, se vi kompili C dosiero, uzu Clang. Kaj tiel cxi tie en mia fari dosieron, kiun mi faras mi diras, ĉi tiu dosiero vi tuj volas kompili kun PDF LaTeX. Kaj tial ĝi estas PDF LaTeX ke tio faras la kompili. Faru ne kompili. Ĝi estas nur kurante tiuj ordonoj en la vico mi specifitaj. Do ĝi kuras PDF LaTeX, ĝi kopias ĝin al la dosierujo Mi volas ke ĝi estu kopiitaj al, ĝi cd al la katalogo kaj faras aliajn aĵojn, sed vi nur faras estas rekoni kiam dosieron ŝanĝoj, kaj se ĝi ŝanĝas, tiam ĝi kuros la komandojn kiujn ĝi estas supozitaj kuri kiam la dosiero ŝanĝojn. >> [Studento] Okay. Mi ne scias, kie la tutmonda fari dosieroj estas por mi kontroli ĝin. Aliaj demandoj? Ion de pasintaj kvizojn? Ajna puntero aferojn? Estas subtilaj aferoj kun indikoj kiel - Mi ne tuj povos trovi kvizon demandon sur ĝi - sed ĝuste kiel ĉi tiajn aferojn. Certiĝu vi komprenas, ke kiam mi diras int * x * y - Tiu ne estas ĝuste nenio ĉi tie, mi supozas. Sed kiel * x * y, tiuj estas 2 variabloj, kiuj estas sur la stako. Kiam mi diras x = malloc (sizeof (int)), x estas ankoraŭ variablo en la pilo, malloc estas iu bloko super en la havaĵo, kaj ni havi x punkto al la amaso. Do iun sur la stako punktoj al la amaso. Kiam ajn vi malloc nenion, vi neeviteble stoki ĝin ene de puntero. Por ke puntero estas sur la stako, la malloced bloko estas sur la muro. Multaj homoj atingas konfuzita kaj diru int * x = malloc; x estas sur la monteto. Ne Kio x notas al estas sur la monteto. x mem estas sur la pilo, se por ajna kialo vi x esti tutmonda variablo, en kies kazo tio okazas al esti en alia regiono de memoro. Do konservanta trako, tiuj skatolo kaj sago diagramoj estas bela komuna por la kvizo. Aŭ se ĝi ne estas sur kvizo 0, ĝi estas sur kvizo 1. Vi devas scii ĉiu de ĉi tiuj, la paŝoj en kompili ĉar vi devis respondi demandojn de tiuj. Jes. [Studento] Could we go super tiuj paŝoj - >> Certe. Antaŭ paŝoj kaj kompili ni havas preprocesamiento, kompili, ariganta, kaj kunligi. Preprocesamiento. Kion tio do? Ĝi estas la plej facila paŝo en - nu, ne kiel - tio ne signifas ke devus esti evidenta, sed ĝi estas la plej facila paŝo. You guys povus apliki ĝin vi mem. Yeah. [Studento] Prenu kion vi havas en via inkludas kiel ĉi tio kaj ĝi kopias kaj poste ankaŭ difinas. Ĝi serĉas aĵojn kiel # include kaj # difini, kaj tio nur kopioj kaj pastes kio tiuj vere signifas. Do kiam vi diras # include cs50.h, la antaŭtraktilo estas kopii kaj bati cs50.h en tiun linion. Kiam vi diras # difini x al esti 4, la antaŭtraktilo iras tra la tuta programo kaj anstataŭas cxia okazoj de x kun 4. Do la antaŭtraktilo prenas validan C dosieron kaj eligas validan C dosieron kie aĵoj estis kopiitaj kaj pasted. Do nun kompili. Kion tio do? [Studento] Ĝi iras de C al duuma. [Bowden] Ne iru la tuta vojo al duuma. [Studento] Por maŝino kodo do? >> Ne maŝino kodo. [Studento] Asembleo? >> Asembleo. Ĝi iras al Asembleo antaux gxi iras tuta vojo al C kodo, kaj plej lingvoj fari ion kiel ĉi tio. Pick ajna altnivela lingvo, kaj se vi iras por kompili ĝin, ĝi estas verŝajna kompili en paŝoj. Unue okazas kompili Python al C, tiam ĝi tuj kompili C al Asembleo, kaj tiam Asembleo tuj get tradukita al duuma. Do kompili tuj alportos ĝin de C al Asembleo. La vorto kompili kutime signifas alporti ĝin de pli alta nivelo al malsupera nivelo programlingvo. Do ĉi tiu estas la sola paŝo en kompilita kie vi komencos kun alta nivelo lingva kaj ili finas en malalta nivelo lingvo, kaj tial la paŝo estas nomata kompili. [Studento] Dum kompili, diru ke vi faris # include cs50.h. Ĉu la tradukilo recompilar la cs50.h, kiel la funkcioj, kiuj estas en tie, kaj traduki ke en Asembleo kodo tiel, aŭ ĉu ĝi kopii kaj almeti ion kiu jam pasis antaŭ-Asembleo? cs50.h estos preskaux neniam finos en Asembleo. Stuff kiel funkcio prototipoj kaj aĵoj estas nur por vi esti singarda. Ĝi garantias ke la tradukilo povas kontroli tion kiel vi vokas funkciojn kun la dekstra reveno tipoj kaj la dekstra argumentoj kaj aĵoj. Do cs50.h estos preprocessed en la dosiero, kaj tiam, kiam ĝi estos kompili ĝi estas esence forĵetis post ĝi certigas ke ĉiu estas nomata ĝuste. Sed la funkcioj difinitaj en la CS50 biblioteko, kiuj estas apartaj de cs50.h, tiuj ne estos aparte kompilita. Tio vere malsupreniru en la ligas paŝo, tial ni atingos ke en dua. Sed unue, kio estas ariganta? [Studento] Asembleo por duuma? >> Jes. Ensamblando. Ni ne nomas ĝin kompili ĉar Asembleo estas preskaux pura traduko de duuma. Estas tre malmulte logiko en irante de Asembleo por duuma. Ĝi simple ŝatus suprenrigardinte en tabulo, oh, ni havas ĉi instrukcion; kiu respondas al duuma 01110. Kaj tial la dosieroj kiuj ensamblando ĝenerale eligoj estas. O dosierojn. Kaj. O dosieroj estas kion ni diras antaŭe, kiel dosiero ne bezonas havi ĉefan funkcion. Ajna dosiero povas kompili suben al. O dosieron, kondiĉe ke ĝi estas valida C dosiero. Ĝi povas esti kompilita ĝis. O. Nun, ligante estas kio vere alportas aron da. O dosierojn kaj alportas ilin al plenumebla. Kaj tiel kion kunligi faras estas vi povas pensi pri la CS50 biblioteko kiel. O dosiero. Estas jam kompilita duuma dosiero. Kaj tiel, kiam vi kompili vian dosieron, via hello.c, kiu nomas GetString, hello.c gets kompilita ĝis hello.o, hello.o estas nun en duuma. Ĝi uzas GetString, do ĝi bezonas por transiri al cs50.o, kaj la enlazador smooshes ilin kune kaj kopias GetString en tiun dosieron kaj eliras kun plenumeblan kiu havas cxiujn funkcioj bezonas. Do cs50.o ne reale ho dosiero, sed ĝi estas sufiĉe proksimaj, ke ne estas fundamenta diferenco. Do kunligi nur alportas aron da dosieroj kune ke aparte enhavi ĉiuj el la funkcioj Mi bezonas uzi kaj kreas la ruleblan kiu vere funkcias. Kaj tiel tio estas ankaŭ, kion ni volus diri antaux kie vi povas havi 1000. c dosierojn, vi kompili ilin ĉiujn al. o dosieroj, kiu probable preni momenton, tiam vi ŝanĝi 1. c dosiero. Vi nur devas recompilar ke 1. C dosiero kaj tiam relink ĉio alia, ligi ĉio reen kune. [Studento] Kiam ni kunligas ni skribi lcs50? Yeah, tiel lcs50. Tiu flago signalojn al la enlazador ke vi devus kunligi en tiu biblioteko. Demandoj? Ĉu ni iris trans duuma aliaj ol 5 sekundoj en la unua prelego? Mi ne kredas tion. Vi devas scii ĉiuj el la grandaj Os ke ni iris trans, kaj vi devus kapabli, se ni donis al vi funkcio, vi devus povi diri ke estas granda a, proksimume. Aŭ bone, granda O estas malglata. Do se vi vidas anidado por maŝojn looping super la sama nombro de aĵoj, kiel int i, i > [studento] n kvadratoj. >> Inklinas esti n kvadratoj. Se vi triobla anidado, ĝi emas esti n potenco de. Por ke tiaj aferoj vi povos atentigi tuj. Vi bezonas scii inserción varo kaj bobelo varo kaj kunfandi varo kaj ĉiuj el tiuj. Estas pli facile kompreni kial ili estas tiuj n kvadratoj kaj n log n kaj ĉiu de tiu ĉar mi kredas ke estis sur kvizon unu jaro, kie ni esence donis al vi realigo de bobelo varo kaj diris, "Kia estas la rula tempo de ĉi tiu funkcio?" Do se vi rekonas ĝin kiel bobelo varo, tiam vi tuj povas diri n kvadratoj. Sed se vi simple rigardi ĝin, vi eĉ ne bezonas por realigi ĝin la bobelo varo; vi povas simple diri ĉi faras tion kaj tion. Tiu estas n kvadratoj. [Studento] Ĉu estas malmola ekzemploj vi povas veni supren kun, kiel similan ideon de elŝeligi? Mi ne kredas ke ni devus doni al vi ajnan malmola ekzemploj. La bobelo speco afero estas proksimume same malfacilaj kiel ni devus iri, kaj eĉ tio, tiom longe kiom vi komprenas, ke vi ripetanta super la tabelo por ĉiu elemento en la tabelo, kiu tuj estos io ke tio n kvadratoj. Estas ĝeneralaj demandoj, kiel ĉi tie ni havas - Oh. Nur la duan tagon, Doug asertis, "mi elpensis algoritmo kiu povas ordigi tabelo "De n nombroj en O (logo n) tempo!" Nu do kiel ni scias, ke estas neeble? [Inaudible studento respondon] >> Jes. Almenaŭ, vi devas tuŝi ĉiu elemento en la tabelo, do ĝi estas neebla al ordigi tabelo de - Se ĉio estas en unsorted ordo, tiam vi tuj estos tuŝi ĉiun en la tabelo, do ĝi estas neeble fari ĝin en malpli ol ho de n. [Studento] Vi montris al ni ke ekzemple de povi fari ĝin en O de n se vi uzas multan memoron. >> Jes. Kaj that's - Mi forgesas, kion that's - Ĉu rakonti speco? Hmm. Tio estas entjero ordigado algoritmo. Mi serĉis la speciala nomo por tio, kion mi ne povis memori lasta semajno. Yeah. Ĉi tiuj estas la tipoj de varoj kiuj povas plenumi tion en granda a de n. Sed estas limigoj, kiel vi nur povas uzi entjeroj ĝis certa nombro. Plus se vi provas ordigi ion that's - Se via tabelo estas 012, -12, 151, 4 milionoj, tiam tiu sola ero tuj tute ruinigi la tutan ordigado. Demandoj? [Studento] Se vi havas rekursie funkcio kaj ĝi nur faras la rekursiaj alvokoj ene de return, jen vosto rekursie, kaj tiel estus ke ne uzas pli memoro dum ekzekuto aŭ ĝi almenaŭ uzi komparebla memoro kiel ripeta solvo? [Bowden] Jes. Ĝi probable estos iom pli malrapida, sed ne vere. Vosto rekursie estas sufiĉe bonaj. Looking denove ĉe pilo kadroj, diru ni havas ĉefan kaj ni havas int trinkejo (int x) aŭ io. Tio ne estas perfekta rekursie funkcio, sed reveno trinkejo (x - 1). Do evidente, ĉi tiu estas misa. Vi bezonas bazon kazoj kaj aĵoj. Sed la ideo estas, ke tio estas vosto rekursie, kio signifas, kiam ĉefa alvokoj trinkejo ĝi tuj trovi ĝian pilo kadro. En ĉi tiu pilo kadro tie Iĝos iom bloko de memoro kiu respondas al lia argumento x. Kaj tiel diru ĉefa okazas nomi trinkejo (100); Do x tuj komenciĝas kiel 100. Se la tradukilo agnoskas ke tiu estas vosto rekursie funkcio, tiam kiam trinkejo faras lia rekursia alvoko por la ekskludo, anstataŭ fari novan pilon kadro, kiu estas kie la pilo komencas kreski grandparte, eventuale ĝi kolizios la amaso kaj tiam vi havos segfaults ĉar memoro komencas karamboli. Do anstataŭ fari sian propran pilo kadro, ĝi povas realigi, hey, mi neniam vere bezonas reveni al ĉi tiu pilo kadro, do anstataŭ mi simple anstataŭigi tiun argumenton kun 99 kaj tiam komenci trinkejo ĉie. Kaj tiam ĝi faros denove kaj ĝin atingos reveno trinkejo (x - 1), kaj anstataŭ fari novan pilon kadro, ĝi estos simple anstataŭigi ĝia aktuala argumento kun 98 kaj tiam salti reen al la komenco de trinkejo. Tiuj operacioj, anstataŭante ke 1 valoro sur la pilo kaj saltante al la komenco, estas sufiĉe efika. Do ne nur estas ĉi la sama memoro uzado kiel aparta funkcio kiu estas ripeta ĉar vi nur uzas 1 pilo kadro, sed vi ne suferas la downsides devi voki funkciojn. Nomante funkcioj povas esti iom multekosta ĉar ĝi devas vidi ĉion ĉi instalinstrukciojn kaj teardown kaj ĉiuj ĉi aferoj. Do tiu vosto rekursio estas bona. [Studento] Kial ne krei novan paŝoj? Ĉar ĝi realigas ĝin ne bezonas. La alvoko al stango ĝuste redoni la rekursiaj alvokon. Do ne bezonas fari ion kun la reveno valoro. Ĝi simple tuj tuj redoni ĝin. Do ĝi estas ĝuste tuj anstataŭos lian propran argumenton kaj komenci pli. Kaj ankaŭ, se vi ne havas la voston rekursie versio, tiam vi ricevis ĉi tiun tutan trinkejoj kie kiam ĉi tiu stango revenas ĝi devas reveni ĝia valoro por ĉi tiu, tiam tiu trinkejo tuj revenas kaj denove lian valoron al ĉi tiu, tiam ĝi estas ĝuste tuj tuj revenos kaj revenu ĝia valoro por ĉi tiu. Do vi ŝparas ĉi krevi ĉiuj tiuj aferoj ekstere de la stako ekde la reveno valoro nur tuj estos pasis tuta vojo reen ĝis ĉiuokaze. Do kial ne simple anstataŭi nian argumenton kun la ĝisdatigita argumento kaj komenci pli? Se la funkcio estas ne vosto rekursia, se vi faros ion kiel - [Studento] se trinkejo (x + 1). >> Jes. Do se vi metas ĝin en kondiĉo, tiam vi faras ion kun la reveno valoro. Aŭ eĉ se vi nur faru reveno 2 * trinkejo (x - 1). Do nun trinkejo (x - 1) bezonas reveni por ke ĝi kalkuli 2 fojoj tiun valoron, tial nun ĝi bezonas propran apartan pilo kadro, kaj nun, kiom ajn vi provos, vi tuj devas - Ĉi tio ne vosto rekursie. [Studento] Ĉu mi provos alporti rekursio noti por voston rekursio - [Bowden] En ideala mondo, sed en CS50 vi ne devas. Por akiri vosto rekursio, ĝenerale, oni starigis plia argumento kie trinkejo prenos int x en y kaj y respondas al la fina afero vi volas reveni. Tial ĉi vi tuj estos reveni trinkejo (x - 1), 2 * y. Por ke estas nur altnivela kiel vi transformos aĵoj esti vosto rekursie. Sed la ekstra argumento - Kaj poste en la fino, kiam vi atingos vian bazon kazo, kiun vi ĵus revenas y ĉar vi estas amasigi la tutan tempon la reveno valoro kiun vi volas. Vi ia estis fari ĝin ripete sed uzante rekursiaj vokoj. Demandoj? [Studento] Eble pri puntero aritmetiko, kiel uzinte kordoj. >> Certe. Pointer aritmetiko. Kiam uzanta kordoj estas facila ĉar kordoj estas char steloj, signoj estas ĉiam kaj ĉiam sola bajto, kaj tiel puntero aritmetiko estas ekvivalento al regula aritmetika kiam vi pritraktas kordoj. Ni nur diras char * s = "saluton". Do ni havas blokon en memoro. Ĝi bezonas 6 bitokoj ĉar vi ĉiam bezonas la nula finilo. Kaj char * s tuj indikas la komencon de ĉi tabelo. Do s notas tie. Nu, temas esence kiel ajna tabelo funkcias, sendepende de ĉu ĝi estas lia reveno de malloc aŭ ĉu ĝi estas je la stako. Ajna tabelo estas esence sagon al la komenco de la tabelo, kaj tiam ajna aro operacio, ajna indeksado, estas ĝuste tuj en tiun tabelo certa kompensi. Do kiam mi diras ion kiel s [3]; ĉi tuj al s kaj rakontante 3 signoj in Do s [3], ni havi 0, 1, 2, 3, do s [3] tuj raporti al ĉi l. [Studento] Kaj ni povis atingi la saman valoron farante s + 3 kaj tiam krampoj stelo? Jes. Tio estas ekvivalento al * (s + 3); kaj tio estas por ĉiam kaj ĉiam ekvivalento negrave kion vi faros. Vi neniam devas uzi la krampo sintakso. Vi povas ĉiam uzi la * (s + 3) sintakson. Homoj emas ŝatas la krampo sintakso, though. [Studento] Tial cxiuj tabeloj estas fakte nur punteros. Estas eta distingo kiam mi diras int x [4]; >> [studento] Does kiuj kreas la memoro? [Bowden] Tio tuj krei 4 ints sur la pilo, do 16 bitokoj entute. Ĝi okazas por krei 16 bitokoj sur la stako. x estas ne stokas ie ajn. Ĝi estas nur simbolo raportante al la komenco de la afero. Ĉar vi deklaris la tabelo ene de ĉi tiu funkcio, kion la tradukilo tuj fari estas simple anstataŭu ĉiujn aperojn de la variablo x kun kie okazis elekti meti tiujn 16 bajtoj. Ĝi ne povas fari tion kun char * s ĉar s estas reala puntero. Ĝi estas libera de tiam indikas aliajn aĵojn. x estas konstanto. Vi ne povas havi ĝin punkto al alia tabelo. >> [Studento] Okay. Sed ĉi tiu ideo, tiu indeksado, estas la sama sendistinge de ĉu ĝi estas tradicia tabelo aŭ se temas pri puntero al iu aŭ se ĝi estas puntero al malloced tabelo. Kaj fakte, ĝi estas tiel ekvivalenta ke tiu estas ankaŭ la sama afero. Ĝi fakte nur tradukas kio estas ene de la krampoj kaj kio restas de la krampoj, aldonas ilin kune, kaj dereferences. Do tiu estas same valida kiel * (s + 3) aŭ s [3]. [Studento] Ĉu vi povas havi punteros indikante 2-dimensia tabeloj? Estas pli malfacile. Tradicie, ne. 2-dimensia tabelo estas nur 1-dimensia tabelo kun iu konvena sintakso ĉar kiam mi diras int x [3] [3], ĉi tiu estas vere nur 1 tabelo kun 9 valoroj. Kaj tiel, kiam mi indico, la tradukilo scias, kion mi volas diri. Se mi diras x [1] [2], scias mi volas iri al la dua vico, do tuj salti la unuaj 3, kaj tiam ŝi volas la dua afero en tio, kio ĝi estas tuj akiri ĉi tiun. Sed estas ankoraŭ nur unu-dimensia tabelo. Kaj tial, se mi volis atribui puntero al tiu tabelo, Mi dirus int * p = x; La tipo de x estas simple - Estas kruda dirante tipo de x ekde ĝi estas nur simbolo kaj ne reala variablo, sed estas nur int *. x estas simple sagon al la komenco de ĉi. >> [Studento] Okay. Kaj do mi ne povos aliri [1] [2]. Mi opinias, ke estas speciala sintakso por deklari pointer, io ridinda kiel int (* p [- io absolute ridinda. mi eĉ ne scias. Sed estas sintakson por deklari punteros kiel kun parentezoj kaj aĵoj. Eble eĉ ne lasu vin fari tion. Mi povus retrorigardas al iu kiu dirus al mi la veron. Mi serĉos ĝin poste, se estas sintakson por punkto. Sed vi neniam vidas. Kaj eĉ la sintakso estas tiel arkaikajn ke se vi uzas gxin, homoj estos barita. Multdimensia tabeloj estas sufiĉe malofta kiel estas. Vi preskaux - Nu, se vi faras matrico aĵoj ĝi ne tuj estos maloftaj, sed en C vi malofte tuj estos uzante multdimensia tabeloj. Yeah. >> [Studento] Imagu ke vi havas vere longan tabelo. Do en virtuala memoro ĝi ŝajnus esti ĉiuj sinsekvaj, kiel la elementoj dekstra flanko de la alia, sed en la fizika memoro, ĉu eblus por esti fendi supren? >> Jes. Kiom virtuala memoro verkoj estas nur disigas - La unueco de atribuo estas iu paĝo, kiu inklinas esti 4 kilobajtoj, kaj tiel kiam procezo diras, hey, mi volas uzi tiun memoron, la mastruma sistemo tuj destini ĝin 4 kilobajtoj por ke iom bloko de memoro. Eĉ se vi uzas nur solan malgrandan bajto en la tuta bloko de memoro, la mastruma sistemo tuj donos al ĝi la plenan 4 kilobajtoj. Do kion tio signifas estas mi povus havi - diru ĉi estas mia pilo. Tiu stako povus esti apartigita. Mia stako eblis megabajtoj kaj megabajtoj. Mia stako povus esti grandega. Sed la pilo mem devas esti dividita en individuaj paĝoj, kio se ni rigardas pli tie diru ĉi estas nia memoro RAM, se mi havas 2 gigabajtoj de RAM, ĉi tiu estas reala adreso 0 kiel la nula bajto de mia memoro RAM, kaj ĉi tiu estas 2 gigabajtoj tuta vojo cxi tie. Do tiu ĉi paĝo povus respondi al ĉi tiu bloko super tie. Ĉi tiu paĝo eble respondas al ĉi tiu bloko super tie. Ĉi tiu povus respondi al ĉi tiu super tie. Do la mastruma sistemo estas libera atribui fizika memoro al ajna individua paĝo arbitre. Kaj tio signifas ke se tiu limo pasas al straddle tabelo, tabelo okazas resti ĉi tio kaj ĝuste de ĉi tiu ordono de artikolo, tiam tiu tabelo tuj estos dividitaj en fizika memoro. Kaj poste, kiam vi forlasis la programon, kiam la procezo finiĝas, tiuj surĵetoj get viŝita kaj tiam ĝi estas libera por uzi ĉi tiuj malgranduloj blokoj por aliaj aĵoj. Pli demandoj? [Studento] La puntero aritmetiko. >> Oh yeah. Kordoj estis pli facilaj, sed rigardante iun kiel ints, do reen al int x [4]; Ĉu ĉi tiu estas tabelo aŭ ĉu ĝi estas puntero al malloced tabelo de 4 entjeroj, ĝi estas tuj estos traktita la sama maniero. [Studento] Do tabeloj estas sur la havaĵon? [Bowden] Arrays estas ne sur la monteto. >> [Studento] Oh. [Bowden] Ĉi tiu tipo de tabelo inklinas esti sur la stako se vi ne deklaris ĝin - ignorante tutmonda variabloj. Ne uzu tutmonda variabloj. Ene de funkcio mi diras int x [4]; Ĝi okazas krei 4-entjero bloko en la pilo por ĉi tabelo. Sed ĉi malloc (4 * sizeof (int)); tuj iros sur la monteto. Sed post tiu punkto mi povas uzi x kaj p en preskaux la sama vojoj, krom la esceptoj mi diris antaŭe pri vi povos reassign p. Teknike, iliaj grandecoj estas tiel malsama, sed tio estas tute pala. Vi neniam vere uzas siajn grandecoj. La p mi povus diri p [3] = 2, aŭ x [3] = 2; Vi povas uzi ilin en ĝuste la sama maniero. Do puntero aritmetiko nun - Jes. [Studento] Cxu vi ne devas fari p * se vi havas la krampoj? La krampoj estas implica dereference. >> Bone. Fakte, ankaŭ kion vi diris per la povas vin preni multdimensia arrays kun indikoj, kion vi povas fari estas io kiel, diru, int ** pp = malloc (sizeof (int *) * 5); Mi nur skribas ĉion el unua. Mi ne volis ke oni. Okay. Kion mi faris tie estas - Tio devus esti pp [i]. Do pp estas puntero al puntero. Vi mallocing pp atentigi al tabelo de 5 int steloj. Do en memoro vi havas sur la stako pp Ĝi tuj indikas tabelo de 5 blokoj, kiuj estas ĉiuj sin punteros. Kaj poste, kiam mi malloc cxi tie, mi malloc ke ĉiu de tiuj individuaj punteros devus celi apartan blokon de 4 bitokoj sur la monteto. Do ĉi punktojn al 4 bitokoj. Kaj ĉi tiu punktoj al malsama 4 bitokoj. Kaj ĉiuj ili notas al siaj propraj 4 bitokoj. Tio donas al mi maniero fari multdimensia aĵoj. Mi povus diri pp [3] [4], sed nun tio ne estas la sama afero kiel matricoj multidimensionales ĉar multdimensia arrays tradukis [3] [4] en sola ofseto en la x tabelo. Ĉi dereferences p, aliroj la tria indekso, tiam dereferences ke kaj aliroj - 4 estus nevalida - la dua indico. Dum kiam ni havis la int x [3] [4] antaux kiel multdimensia tabelo kaj kiam vi duoble krampo estas vere nur sola dereference, vi sekvas sola puntero kaj poste kompensi, ĉi tio estas vere 2D referencoj. Vi sekvu 2 apartajn punteros. Do ĉi tiu ankaŭ teknike permesas havi multdimensia arrays kie ĉiu individuo tabelo estas malsamaj grandecoj. Do mi pensas pintaj multdimensia tabeloj estas kio ĝi estas nomata ekde vere la unua kiu povus noti al iu kiu havas 10 elementoj, la dua afero povus noti al iu kiu havas 100 eroj. [Studento] Ĉu estas limo al la nombro de punteros vi povas havi montrante al aliaj indikoj? >> No Vi povas havi int ***** p. Reen al puntero aritmetiko - >> [studento] Oh. >> Jes. [Studento] Se mi havas int *** p kaj tiam mi fari dereferencing kaj mi diras p * estas egala al tiu valoro, Estas nur faros 1 nivelo de dereferencing? >> Jes. Do se mi volas aliri la aferon ke la lasta puntero notas en - Tiam vi faras *** p. >> Bone. Do tiu estas p poentojn al 1 bloko, punktoj al alia bloko, punktoj al alia bloko. Tiam se vi faras * p = io, tiam vi ŝanĝi ĉi nun notas al malsama bloko. >> Bone. [Bowden] Kaj se tiuj estis malloced, tiam vi nun filtris memoro se vi hazarde havas malsamajn referencoj de tiuj ĉar vi ne povas reiri al tiuj kiuj vi ĵus forĵetis. Pointer aritmetiko. int x [4]; tuj destini tabelo de 4 entjeroj kie x iras rekte al la komenco de la tabelo. Do kiam mi diras ion kiel x [1], mi volas ke ĝi signifas iri al la dua entjera en la tabelo, kiu estus tiu ĉi. Sed vere, jen 4 bajtoj en la tabelo ekde ĉi entjero okupas 4 bitokoj. Do oni kompensas el 1 vere signifas kompensi el 1 fojoj la grandeco de kiom la tipo de la tabelo estas. Jen tabelo de entjeroj, do scias fari 1 fojoj grandeco de int kiam volas kompensi. La alia sintakso. Memoru ke ĉi tio estas ekvivalento al * (x + 1); Kiam mi diras puntero + 1, kion tiu revenas estas la adreso, ke la montrilo estas stokante plus 1 fojoj la grandeco de la tipo de la puntero. Do se x = ox100, tiam x + 1 = ox104. Kaj vi povas trouzi tion kaj diri iun kiel char * c = (char *) x; kaj nun c tuj estos la sama adreso kiel x. c tuj estos egala al ox100, sed c + 1 tuj estos egala al ox101 ekde puntero aritmetiko dependas de la tipo de la puntero ke vi aldonante. Do c + 1, ĝi rigardas c, estas char pointer, do tuj aldoni 1 fojoj grandeco de char, kiu ĉiam iras al esti 1, do vi ricevis 101, dum se mi faras x, kiu estas ankaŭ ankoraŭ 100, x + 1 tuj estos 104. [Studento] Ĉu vi povas uzi c + + por antaŭi vian puntero de 1? Jes, vi povas. Vi ne povas fari tion kun x ĉar x estas nur simbolo, estas konstanta; vi ne povas ŝanĝi x. Sed c okazas nur esti puntero, do c + + estas perfekte valida kaj ĝi estos pliigo de 1. Se c estis nur int *, tiam c + + estus 104. + + Does puntero aritmetiko kiel c + 1 estus farinta puntero aritmetiko. Tiu estas fakte kiel multajn aferojn kiel merge speco - Anstataŭ krei kopiojn de aferoj, vi povos anstataŭ pasi - Kiel se mi volis pasi tiun duono de la tabelo - Ni viŝi iuj de ĉi. Diru Mi volis pasi ĉi tiu flanko de la tabelo en funkcio. Kion mi parolu pri tiu funkcio? Se mi pasi x, mi pasante ĉi tiu adreso. Sed mi volas pasi ĉi aparta adreso. Do kion mi devas pasi? [Studento] Pointer + 2? [Bowden] Do x + 2. Jes. Tio tuj estos ĉi tiu adreso. Vi ankaŭ tre ofte vidas kiel x [2] kaj tiam la adreso de tiu. Do vi bezonas preni la adreson de ĝi ĉar la krampo estas implica dereference. x [2] indikas la valoron, kiu estas en ĉi tiu skatolo, kaj tiam vi volas ke la adreso de tiu skatolo, tial vi diras & x [2]. Do jen kiel io en merge speco kie vi volas pasi duono la listo al iu vi vere nur pasi & x [2], kaj nun ĝis la rekursia alvoko raportas, mia nova tabelo komenciĝas tie. Lasta minuto demandoj. [Studento] Se ni ne enmetu signo aŭ - kio estas tio nomita? >> Stelo? [Studento] Stelo. >> Teknike, dereference operatoro, sed - >> [studento] Dereference. Se ni ne metas stelo aŭ signo, kio okazas se mi simple dirus y = x kaj x estas puntero? Kio estas la tipo de y? >> [Studento] Mi nur diru ke estas puntero 2. Do, se vi simple diru y = x, nun x kaj y punkton al la sama afero. >> [Studento] Punkto al la sama afero. Kaj se x estas int puntero? >> Estus plendas ĉar oni ne povas atribui punteros. [Studento] Okay. Memoru ke punteros, kvankam ni desegni ilin kiel sagoj, vere cxiuj vendejo - int * x - vere ĉiuj x estas stokante estas io kiel ox100, kiuj ni okazi por reprezenti kiel indikante la bloko stokitaj en 100. Do kiam mi diras int * y = x; Mi simple kopiado ox100 en y, kiuj ni estas ĝuste tuj reprezentos kiel y, ankaŭ indikante ox100. Kaj se mi diras int i = (int) x, tiam i tuj stoki ajn la valoro de ox100 estas interne de ĝi, sed nun tuj esti interpretita kiel entjero anstataŭ puntero. Sed vi bezonas la dividon alie ĝi plendas. [Studento] Do vi volas diri, ke ili elpelu - Ĉu tuj estos malpleniginta int de x aŭ casting int de y? [Bowden] Kio? [Studento] Okay. Post tiuj parentezoj estas tie tuj estos x aŭ ay tie? [Bowden] Aŭ. x kaj y estas ekvivalentaj. >> [Studento] Okay. Ĉar ili estas ambaŭ punteros. >> Jes. [Studento] Do devus stoki la deksesuma 100 en entjera formo? >> [Bowden] Yeah. Sed ne la valoron de ĉiu kiu notas al. [Bowden] Yeah. >> [Studento] Do nur la adreson en entjera formo. Okay. [Bowden] Se vi volas por iu stranga kialo, vi povus ekskluzive trakti punteros kaj neniam pritrakti entjeroj kaj nur estu kiel int * x = 0. Tiam vi tuj get vere konfuzita unufoje puntero aritmetiko startas okazas. Do la nombro ke ili stokas estas sensignifa. Estas nur ke vi finos interpreti ilin. Do mi estas libera por kopii ox100 el int * al int, kaj mi rajtas asigni - you're probable tuj get kriis al por ne jxetantajn - Mi estas libera atribui iun kiel (int *) ox1234 en tiun arbitran int *. Do ox123 estas same valida memoro adreso kiel estas & y. & Y okazas reveni iu kiu estas preskaux ox123. [Studento] Ĉu tiu esti vere malvarmeta vojo iri de deksesuma al decimala formo, kiel se vi havas puntero kaj ĵetas ĝin kiel int? [Bowden] Vi povas vere nur presi uzante kiel printf. Diru Mi havas int y = 100. Do printf (% d \ n - kiel vi devus jam scii - presi ke kiel entjero,% x. Ni simple presas ĝin kiel deksesuma. Do puntero ne stokas kiel deksesuma, kaj entjero ne stokas kiel decimala. Ĉio estas stokita kiel duuma. Estas nur ke ni emas montri punteros kiel deksesuma ĉar ni pensu pri tio en tiuj 4-bajto blokoj, kaj memoro adresoj inklinas esti familiara. Ni ŝatas, se ĝi komenciĝas per bf, tiam okazas al esti sur la stako. Do estas nur nia interpreto de punteros kiel deksesuma. Okay. Ajna lastaj demandoj? Mi estos tie por iom post se vi havas ion alian. Kaj tio estas la fino de tiu. [Studento] Yay! [Aplaŭdo] [CS50.TV]