[Muzika] DOUG Lloyd: Pointers, këtu jemi. Kjo është ndoshta do të të jetë tema më e vështirë që ne flasim për në CS50. Dhe në qoftë se ju keni lexuar asgjë për pointers para se ju mund të jetë pak frikësuese shkon në këtë video. Është e vërtetë pointers do t'ju lejojë mundësinë për të ndoshta vidhos deri goxha keq kur ju jeni duke punuar me variablat, dhe të dhënat, dhe duke shkaktuar programin tuaj për të rrëzuar. Por ata janë në fakt të vërtetë të dobishme dhe ata na një mënyrë të vërtetë të madhe të lejuar për të kaluar dhëna mbrapa dhe radhë midis funksioneve, se ne jemi ndryshe në gjendje të bëjë. Dhe kështu ajo që ne me të vërtetë dua të bëj këtu është tren ju të keni disiplinë të mirë akrep, kështu që ju mund të përdorni në mënyrë efektive pointers për të bërë programet tuaja që shumë më mirë. Siç thashë pointers të na japë një tjetër mënyrë për të kaluar të dhënave në mes funksioneve. Tani në qoftë se ju kujtohet nga një video të parë, kur ne ishim duke folur për Shtrirja e ndryshueshme, e përmenda që të gjitha të dhënat që ne të kalojë në mes të Funksionet në C është miratuar nga vlera. Dhe unë nuk mund të ketë përdorur atë afat, ajo që unë do të thotë atje ishte se ne jemi duke kaluar kopje të të dhënave. Kur ne të kalojë një ndryshore në një funksion, ne nuk jemi në fakt kaluar ndryshueshme në funksion, e drejtë? Ne jemi duke kaluar një kopje që të dhënat e funksionit. Funksioni bën atë që do dhe ajo llogarit disa vlera, dhe ndoshta ne i përdorim se vlera kur ajo i jep atë përsëri. Nuk ishte një përjashtim për Ky rregull i kalonte vlerë, dhe ne do të kthehen në atë që është pak më vonë në këtë video. Në qoftë se ne përdorim pointers në vend e përdorimit të variablave, ose në vend të përdorimit të variablave vetë ose kopjet e variablave, ne tani mund të kalojë variablat rreth ndërmjet funksioneve në një mënyrë të ndryshme. Kjo do të thotë se në qoftë se ne kemi bërë një ndryshim në një funksion, se ndryshimi në fakt do të marrë efekt në një funksion të ndryshëm. Përsëri, kjo është diçka që ne nuk mund të bëjmë më parë, dhe në qoftë se ju keni provuar ndonjëherë për të bie në ujdi Vlera e dy variablave në një funksion, e keni vënë re këtë problem lloj i zvarrit deri, e drejtë? Në qoftë se ne duam të bie në ujdi X dhe Y, dhe ne të kalojë ato në një funksion të quajtur shkëmbim, brenda i funksionit shkëmbim Variablat bëjnë vlerat e këmbimit. Një bëhet dy, dy bëhet një, por ne nuk e bëjmë në fakt ndryshojë asgjë në origjinal funksion, në thirrësi. Sepse ne nuk mund, ne jemi vetëm duke punuar me kopje të tyre. Me pointers pse, ne mund të në fakt kalojnë X dhe Y në një funksion. Se funksioni mund të bëjë diçka me ta. Dhe këto vlera variablat në fakt mund të ndryshojë. Pra, kjo është mjaft e një ndryshim në aftësia jonë për të punuar me të dhëna. Para se të pikiatë në pointers, unë mendoj se është me vlerë duke marrë disa minuta për të të kthehemi në bazat këtu. Dhe të ketë një sy se si Punimet e kujtesës kompjuter për shkak se këto dy subjekte janë duke shkuar që në fakt të jetë goxha të ndërlidhura. Si ju ndoshta e dini, në sistemin tuaj kompjuterik ju keni një hard drive ose ndoshta një makinë solide të shtetit, një lloj i lokacionit file storage. Kjo është zakonisht diku në lagje prej 250 gigabajt për të ndoshta disa terabytes tani. Dhe kjo është ku të gjithë tuaj fotografi në fund të fundit jetojnë, edhe kur kompjuteri juaj është i mbyllur jashtë, ju mund ta kthejnë atë përsëri në dhe ju do të gjeni dosjet tuaja janë atje përsëri kur ju reboot sistemin tuaj. Por disk drives, si një hard disk drive, një HDD, apo një makinë solide të shtetit, një SSD, janë vetëm hapësira e magazinimit. Ne nuk mund të vërtetë të bëjë asgjë me të dhënat që është në hard disk, ose në një makinë të ngurta shtetëror. Në mënyrë që në fakt ndryshojnë të dhëna ose të lëvizin atë rreth, ne duhet të lëvizin atë në RAM, kujtesë e gjallë. Tani RAM, ju keni një shumë më pak në kompjuterin tuaj. Ju mund të keni diku në lagje e 512 MB në qoftë se ju keni një kompjuter të vjetër, për ndoshta dy, katër, tetë, 16, ndoshta edhe pak më shumë, gigabajt të RAM. Pra, kjo është shumë më e vogël, por kjo është ku të gjitha të dhënave të paqëndrueshme ekziston. Kjo është ku ne mund të ndryshojmë gjërat. Por, kur jemi kthyer kompjuterin tonë jashtë, të gjitha të dhënat në RAM është shkatërruar. Pra, kjo është arsyeja pse ne duhet të kemi hard disk për vendndodhjen më të përhershëm të saj, në mënyrë që ajo exists- kjo do jetë me të vërtetë i keq në qoftë se çdo herë kemi kthyer kompjuterin tonë jashtë, çdo skedar në sistemin tonë ishte zhdukur. Pra, ne punojmë brenda RAM. Dhe çdo herë që ne jemi duke folur për kujtesës, shumë e shumë, në CS50, ne jemi duke folur për RAM, jo hard disk. Pra, kur ne shkojmë gjëra në kujtesë, ajo merr një sasi të caktuar të hapësirës. Të gjitha llojet e të dhënave që ne kemi qenë duke punuar me të marrë të ndryshme shumat e hapësirës në RAM. Pra, çdo herë që ju të krijoni një numër të plotë ndryshueshme, katër byte memorje janë vendosur mënjanë në RAM kështu ju mund të punojnë me atë numër të plotë. Ju mund të deklarojë integer, ndryshuar atë, të caktojë atë me një vlerë 10 incremented nga një, kështu me radhë e kështu me radhë. E gjithë kjo duhet të ndodhë në RAM, dhe që ju të merrni katër bytes për të punuar me të për çdo numër i plotë që keni krijuar. Çdo karakter ju krijojë merr një bajt. Kjo është vetëm sa hapësirë ​​është të nevojshme për të ruajtur një karakter. Çdo noton, një e vërtetë numër, merr katër bytes nëse kjo është një dyfishtë precision pikë lundrues numër, i cili ju lejon të kanë shifra më të sakta ose më shumë pas presjes dhjetore pa humbur saktësi, që marrin tetë byte memorje. Dëshiron gjata, integers vërtetë të mëdha, gjithashtu marrin tetë byte memorje. Sa byte memorje do të strings marrë? E pra, le të vënë një gjilpërë me kokë në këtë pyetje tani për tani, por ne do të kthehen në të. Pra, përsëri në këtë idenë e kujtesës si një grup i madh i qelizave byte-sized. Kjo është me të vërtetë e gjitha kjo është, kjo është vetëm një grup të madh të qelizave, ashtu si çdo grup tjetër që ju jeni të njohur me të dhe të shohim, me përjashtim të çdo element është një bajt gjerë. Dhe vetëm si një grup, çdo element ka një adresë. Çdo element i një sërë ka një indeks, dhe ne mund të përdorin këtë indeks për të bërë të ashtuquajtur qasje të rastësishme në grup. Ne nuk duhet të fillojë në fillimi i vektorit, iterate nëpër çdo element të vetme të tyre, për të gjetur atë që ne jemi duke kërkuar për. Ne mund të them vetëm, unë dua të merrni të Elementi 15 apo elementi 100. Dhe ju mund vetëm të kalojë në këtë numër dhe për të marrë vlerën që ju po kërkoni. Në mënyrë të ngjashme çdo vend në kujtesën e ka një adresë. Pra, kujtesa juaj mund të duket diçka si kjo. Këtu është një copë shumë e vogël e kujtesës, kjo është 20 bytes të memories. 20 bytes e parë, sepse im drejtohet ka në pjesën e poshtme janë 0, 1, 2, 3, dhe kështu në të gjithë rrugën deri në 19. Dhe kur unë deklaroj variablave dhe kur unë të fillojë për të punuar me ta, sistemi do të vendosur mënjanë disa hapësirë ​​për mua në këtë kujtim për të punuar me variablat e mia. Kështu që unë mund të them, char c është e barabartë me kapitalin H. Dhe çfarë do të ndodhë? Pra sistemi do të vendosur mënjanë për mua një byte. Në këtë rast ajo zgjodhi numrin byte katër, byte në adresën katër, dhe ajo do të ruajtur H shkronjë kapitale në atje për mua. Në qoftë se unë them shpejtësi int Kufiri i barabartë 65, është duke shkuar për të lënë mënjanë katër bytes të memories për mua. Dhe ajo do të trajtojmë ata katër bytes si një njësi e vetme sepse ajo që ne jemi duke punuar me eshte nje numer ketu. Dhe ajo do të ruajtur 65 në atje. Tani tashmë unë jam natyrë e ju thënë një grimë e një gënjeshtër, e drejtë, sepse ne e dimë se kompjuterët punojnë në binar. Ata nuk e kuptojnë domosdo se çfarë është një H kapital është apo çfarë është një 65 është, ata vetëm kuptojnë binare, zero dhe ato. Dhe kështu në fakt, çfarë ne jemi ruajtjen në atje nuk është letër H dhe numri 65, por më tepër përfaqësime binare e tyre, të cilat duken një pak diçka si kjo. Dhe në veçanti në Konteksti i variablit numër i plotë, kjo nuk do të vetëm të nxjerr atë në, kjo nuk do të trajtojnë atë si një katër byte copë domosdoshmërisht, kjo është në të vërtetë do për të trajtuar atë si një katër chunks byte, e cila mund të duket diçka si kjo. Dhe, edhe kjo nuk është e krejtësisht e vërtetë ose, për shkak të diçka të quajtur një endianness, të cilat ne nuk jemi do të merrni në tani, por në qoftë se ju jeni kurioz rreth, ju mund ta lexoni deri në pak dhe endianness mëdha. Por, për hir të këtij argumenti, për hir të kësaj video, le të supozojmë se është, në fakt, si numri 65 do të të përfaqësohen në kujtesës në çdo sistem, edhe pse kjo nuk është plotësisht e vërtetë. Por le të vërtetë të merrni vetëm shpëtoj të gjithë binar tërësisht, dhe vetëm mendojnë për sa H dhe 65, kjo është një shumë më e lehtë të mendojnë për atë si se si një qenie njerëzore. Të gjithë të drejtë, kështu që gjithashtu duket ndoshta një pak të rastit që I've- sistemi im nuk ka dhënë më bytes 5, 6, 7, dhe 8 të ruajtur numër i plotë. Ka një arsye për këtë, gjithashtu, që ne nuk do të marrë në të drejtë tani, por mjafton kjo për të thënë se çfarë kompjuteri është bërë këtu është ndoshta një masë e mirë nga ana e saj. Për të mos më jepni kujtesës që është domosdoshmërisht për të kthyer prapa. Edhe pse ajo do të bëjë atë tani në qoftë se unë dua të të marrë një tjetër varg, quajtur mbiemri, dhe unë dua për të vënë Lloyd në atje. Unë do të duhet të përshtaten një karakter, çdo letër prej se është do të kërkojë një karakter, një bajt memorie. Pra, nëse unë mund të vënë Lloyd në rrjet e mia si kjo unë jam goxha i mirë për të shkuar, e drejtë? Çfarë është zhdukur? Mos harroni se çdo varg ne punojmë me në C përfundon me backslash zero, dhe ne nuk mund të harroj se këtu, ose. Ne kemi nevojë për të vënë mënjanë një bajt e kujtesës për të mbajtur atë kështu që ne e di kur string jonë ka përfunduar. Pra, përsëri kjo marrëveshje e mënyrën gjërat shfaqet në fuqinë e kujtesës të jetë pak të rastit, por ajo në fakt është se si shumica e sistemeve janë të dizajnuara. Të vijë atyre në multiples e katër, për arsye përsëri që ne nuk kemi nevojë të merrni në të drejtë tani. Por kjo, kështu që mjafton të themi se pas këtyre tre rreshta të kodit, kjo është ajo që e kujtesës mund të duket si. Nëse kam nevojë për vende të kujtesës 4, 8, 12 dhe për të mbajtur të dhënat e mia, kjo është ajo që kujtesa ime mund të duket si. Dhe vetëm të jetë veçanërisht e pedant këtu, kur ne jemi duke folur për kujtesën Adresat Ne zakonisht bëjë këtë duke përdorur notations heksadecimal. Pra, pse nuk kemi kthyer të gjitha këto nga decimal të simbol heksadecimal vetëm për shkak se kjo është në përgjithësi si ne i referohemi kujtesës. Pra, në vend të të qenit 0 përmes 19, ajo që ne kemi është zero x zero përmes zero x1 tre. Këto janë 20 bytes e kujtesës që ne kanë ose ne jemi duke kërkuar në në këtë imazh mu ketu. Pra, të gjitha që u tha, le të hap larg nga kujtesa për një të dytë dhe të kthehet në pointers. Këtu është më e rëndësishme gjë për të kujtuar si ne të fillojë të punojë me pointers. Një tregues është asgjë më shumë se një adresë. Unë do të them atë përsëri për shkak është e rëndësishme që, një tregues nuk është asgjë më shumë se një adresë. Pointers janë adresat në vende në kujtesën ku variabla jetojnë. Duke ditur se bëhet shpresojmë se një pak më e lehtë për të punuar me ta. Një tjetër gjë që unë doja të bëni është që të ketë lloj Diagramet e vizualisht përfaqësojnë çfarë është ndodh me linjat e ndryshme të kodit. Dhe ne do të bëjmë këtë një çift e herë në pointers, dhe kur ne flasim për dinamik kujtese si. Sepse unë mendoj se këto diagramet mund të jetë veçanërisht e dobishme. Pra, nëse unë them për shembull, int k në kodin tim, çfarë po ndodh? E pra çfarë po ndodh në thelb është Unë jam marrë kujtesës caktuar për mua, por edhe unë nuk doja të mendoni rreth saj si kjo, unë si të mendojnë për atë si një kuti. Unë kam një kuti dhe kjo është me ngjyrë të gjelbër për shkak se unë mund të vënë integers në kuti të gjelbër. Në qoftë se ajo ishte një karakter i mund të ketë një kuti blu. Por unë gjithmonë them, në qoftë se unë jam duke krijuar një kuti që mund të mbajë integers se kuti është me ngjyrë të gjelbër. Dhe unë të marrë një shënues të përhershëm dhe unë shkruaj k në anën e saj. Pra, unë kam një kuti të quajtur k, në të cilën unë mund të vënë integers. Pra, kur unë them int k, kjo është çfarë ndodh në kokën time. Nëse unë them k është e barabartë me pesë, çfarë jam unë duke bërë? E pra, unë jam vënë pesë në kuti, e drejtë. Kjo është shumë i thjeshtë, në qoftë se Unë them int k, të krijojë një kuti të quajtur k. Nëse unë them k është e barabartë me 5, i vendosi pesë në kuti. Shpresojmë që nuk është shumë e një kërcim. Ja ku gjërat shkojnë një pak interesante edhe pse. Nëse unë them int * pk, dhe edhe në qoftë se unë nuk e bëj e di se çfarë kjo do të thotë detyrimisht, atë e mori në mënyrë të qartë diçka të bëjë me një numër të plotë. Kështu që unë jam duke shkuar për ngjyra kjo kuti e gjelbër-ish, Unë e di se ka diçka të bëjë me një numër të plotë, por kjo nuk është një numër i plotë në vetvete, sepse kjo është një yll int. Ka diçka pak ndryshme në lidhje me të. Pra, përfshirë një numër të plotë-së, por ndryshe është jo shumë e ndryshme nga atë që ne ishim duke folur rreth. Kjo është një kuti, e saj mori një etiketë, ajo është veshur me një pk etiketë, dhe kjo është e aftë të mbajnë Yjet int, çfarëdo që ata janë. Ata kanë diçka për të bërë me integers, në mënyrë të qartë. Këtu është vija e fundit pse. Nëse unë them PK = & k, ee, çfarë ka ndodhur vetëm, e drejtë? Pra ky numër të rastit, në dukje të rastit numër, merr hedhur në kutinë e atje. E gjithë kjo është, është pk merr adresën e k. Kështu që unë jam i fërkimit ku k jeton në kujtesë, adresën e tij, adresa e bytes saj. Të gjitha unë jam duke bërë është që unë jam duke thënë se kjo vlerë është ajo që unë jam duke shkuar për të vënë brenda kuti të quajtur PK tim. Dhe për shkak se këto gjëra janë pointers, dhe për shkak kërkim në një varg si zero x tetë zero c shtatë katër tetë dy zero është ndoshta jo shumë kuptimplotë. Kur ne përgjithësi kujtoj pointers, ne fakt e bëjnë këtë si pointers. Pk na jep informacion ne kemi nevojë për të gjetur k në kujtesë. Pra, në thelb pk ka një shigjetë në të. Dhe nëse ecim gjatësinë e atij shigjetë, imagjinoni kjo është diçka që ju mund të ecin në, në qoftë se ne ecin përgjatë gjatësisë së shigjetës, në majë shumë të atij shigjetës, ne do të gjeni vend në kujtesën e ku k jeton. Dhe kjo është me të vërtetë e rëndësishme sepse një herë ne e dimë se ku jeton k, ne mund të fillojnë të punojnë me të dhënat brenda atë vend kujtesës. Edhe pse ne jemi duke marrë një teeny pak përpara vetes për tani. Pra, çfarë është një akrep? Një tregues është një artikull dhënat e të cilit Vlera është një adresë e kujtesës. Kjo ishte se zero x tetë zero sende në vazhdim e sipër, që ishte një adresë kujtim. Kjo ishte një vend në kujtesë. Dhe llojin e një akrep përshkruan llojin e të dhënave që ju do të gjeni në se adresa memorike. Pra, ka të drejtën ylli int pjesë. Nëse unë ndjek atë shigjetë, është do të më çojë në një vend. Dhe kjo vendndodhja, ajo që unë do të gjeni atje në shembullin tim, është një kuti e gjelbër me ngjyrë. Është një numër i plotë, kjo është ajo që unë do të gjeni nëse unë shkoj në atë adresë. Lloji dhënat e një akrep përshkruan çfarë ju do të gjeni në këtë adresë e kujtesës. Kështu që këtu është gjë me të vërtetë cool pse. Pointers të na lejojë të kalojë Variablat mes funksioneve. Dhe në fakt kalojnë variablave dhe jo të kalojë kopje të tyre. Sepse në qoftë se ne e dimë saktësisht se ku në kujtesë për të gjetur një ndryshore, ne nuk kemi nevojë për të bërë një kopje të ajo, ne vetëm mund të shkojnë në atë vend dhe të punojnë me këtë variabël. Pra, në thelb pointers lloj e bëjnë një mjedis kompjuter shumë më shumë si në botën e vërtetë, e drejtë. Kështu që këtu është një analogji. Le të thonë se unë kam një fletore, e drejtë, dhe kjo është e plotë të shënimeve. Dhe unë do të doja që ju të rinovuar atë. Ju jeni një funksion që përditësime shënime, e drejtë. Në mënyrën se si ne kemi qenë punuar deri më tani, çfarë ndodh është që ju do të marrë fletoren time, ju do të shkoni në dyqan kopje, ju do të bëni një kopje të Xerox çdo faqe e fletore. Ju do të lënë fletoren e mia në tryezën time, kur ju jeni bërë, ju do të shkoni dhe të kalojnë gjëra në tim fletore që janë nga data apo e gabuar, dhe pastaj ju do të kalojë përsëri në më rafte e faqeve Xerox që është një kopje e fletoren time me ndryshimet që ju keni bërë për të. Dhe në këtë pikë, është deri në mua si funksioni quajtur, si telefonuesi, për të vendosur për të marrë shënimet tuaja dhe integrimin e tyre përsëri në fletoren time. Pra, ka shumë hapa përfshirë këtu, e drejtë. Ashtu si nuk do të ishte më mirë në qoftë se unë vetëm them, hej, ju mund të rinovuar fletoren time për mua, ju dorë fletoren time, dhe ti marrin gjërat dhe fjalë për fjalë kalojnë ato dhe përditësimin shënimet e mia në fletoren time. Dhe pastaj jepni fletoren time mbrapa. Kjo është lloj i asaj që pointers të na lejojë të bëjmë, ata e bëjnë këtë mjedis shumë më shumë si se si ne të veprojë në realitet. Të gjithë të drejtë kështu që kjo është ajo një akrep është, le të flasim për mënyrën se si pointers punojnë në C, dhe se si ne mund të fillojnë të punojnë me ta. Pra, ka një tregues shumë i thjeshtë në C quajtur treguesin null. Pikat null tregues për asgjë. Kjo ndoshta duket sikur është në fakt nuk është një gjë shumë e dobishme, por si ne do të shohim një pak më vonë, fakti se ky tregues null ekziston vërtetë me të vërtetë mund të jetë në dispozicion. Dhe sa herë që ju të krijoni një akrep, dhe ju nuk e vënë immediately- vlera e tij një shembull i përcaktimit vlera e tij menjëherë do të jetë një çift slides mbrapa ku kam thënë pk barabartë & K, pk merr adresën K-së, si ne do të shohim se çka do të thotë, ne do të shohim se si të kodit që shortly- në qoftë se ne nuk e vendosur vlerën e saj për diçka kuptimplotë menjëherë, ju duhet gjithmonë vendosur treguesin tuaj të tregojnë për null. Ju duhet të vënë atë të tregojnë për asgjë. Kjo është shumë e ndryshme se vetëm duke e lënë vlerën siç është dhe pastaj duke deklaruar një tregues dhe vetëm duke supozuar është null, sepse kjo është e vërtetë rrallë. Kështu që ju duhet gjithmonë të vendosur vlera e një tregues të null nëse ju nuk e vënë vlerën e saj diçka kuptimplotë menjëherë. Ju mund të kontrolloni nëse një tregues i vlerës është i pavlefshëm duke përdorur operatorin e barazisë (==), Ashtu si ju krahasoni ndonjë numër i plotë Vlerat ose vlerat karakter duke përdorur (==) gjithashtu. Kjo është një lloj i veçantë i vazhdueshëm Vlera që ju mund të përdorni për të testuar. Kështu që ishte një shumë e thjeshtë pointer, tregues null. Një tjetër mënyrë për të krijuar një tregues është për nxjerrjen adresa e një variable keni krijuar tashmë, dhe ju bëni këtë duke përdorur & Nxjerrja adresë operator. Të cilat ne kemi parë tashmë më parë në shembullin e parë diagram kam treguar. Pra, nëse x është një ndryshore që ne kemi tashmë e krijuar e tipit numër i plotë, atëherë dhe x është tregues për një numër të plotë. dhe x është- mbani mend, dhe do të nxjerrë adresa e gjë në të djathtë. Dhe që nga një tregues është vetëm një adresë, se dhe x është tregues për një numër të plotë vlera e të cilit është vendi ku në jetën e kujtesës x. Kjo është adresa e X-it. Pra, & x është adresa e x. Le të marrin këtë hap një më tej dhe të lidheni me diçka Kam përmendur tërthorazi në një video paraprak. Nëse arr është një grup i dyshe, atëherë & arr kllapa katrore i është një tregues për një të dyfishtë. NE RREGULL. arr kllapa katrore unë, kur arr është një grup i dyshe, pastaj arr kllapa katrore i është elementi i-th e atij grup, dhe & arr kllapa katrore i është ku në kujtesës elementi i-th e arr ekziston. Pra, çfarë është implikimi këtu? Një emër vargjeve, implikimi e këtë gjë të gjithë, është se emri i një grup është në fakt në vetvete një akrep. Ju keni qenë duke punuar me pointers të gjithë së bashku çdo herë që ju keni përdorur një koleksion. Mbani mend nga shembulli në fushëveprimin e ndryshueshme, pranë fund të video unë i pranishëm një shembull ku ne kemi një funksion quajtur int grup dhe një Funksioni i quajtur set array. Dhe sfida juaj për të përcaktuar nëse janë apo jo, apo çfarë Vlerat që ne të shtypura jashtë fundi i funksionit, ne fund te programin kryesor. Nëse ju kujtohet nga ajo shembull ose në qoftë se ju keni shikuar videon, ju e dini se kur ju-thirrjen për grup int efektivisht nuk bën asgjë. Por thirrja për të vendosur grup bën. Dhe unë lloj i glossed mbi pse që ishte rasti në atë kohë. Unë vetëm tha, pra kjo është një grup, është e të veçantë, ju e dini, ka një arsye. Arsyeja është se një grup të Emri është me të vërtetë vetëm një tregues, dhe ka këtë të veçantë katror sintaksë kllapa se bëjë gjëra shumë nicer për të punuar me të. Dhe ata e bëjnë idenë e një treguesin shumë më pak frikësuese, dhe kjo është arsyeja pse ata janë lloj e paraqitur në këtë mënyrë. Por me të vërtetë vargjeve janë vetëm pointers. Dhe kjo është arsyeja pse kur ne bëri një ndryshim në grup, kur kemi kaluar një grup si një parametër në një funksion ose si një argumenti në një funksion, përmbajtja e vektorit ndryshuar në të vërtetë në të dy callee dhe në thirrësit. I cili për çdo lloj tjetër të ndryshore pamë nuk ishte rasti. Pra, kjo është vetëm diçka për të mbajtur në mendje kur ju jeni duke punuar me pointers, është se emri i një array në fakt një tregues të elementit të parë të kësaj vektorit. OK kështu që tani kemi të gjitha këto fakte, le të mbajë, apo jo. Pse nuk kemi kujdes për ku diçka jeton. Edhe si i tha, kjo është goxha e e dobishme të dinë se ku jeton diçka kështu që ju mund të shkoni atje dhe për të ndryshuar atë. Punojnë me të dhe në fakt kanë gjë që ju dua të bëj për këtë qëllim ndryshueshme të marrë, dhe jo të hyjë në fuqi në disa kopje të saj. Kjo quhet dereferencing. Ne do të shkojmë në referencës dhe ne të ndryshojë vlerën atje. Pra, nëse ne kemi një tregues dhe është quajtur pc, dhe kjo tregon për një karakter, atëherë mund të themi * pc dhe pc * është Emri i asaj që ne do të gjeni nëse ne do të shkojmë në pc adresën. Ajo që ne do të gjeni se ka një karakter dhe * pc është se si ne i referohemi të dhënave në atë Vendndodhja. Pra, ne mund të themi diçka si * pc = D ose diçka të tillë, dhe kjo do të thotë se çdo gjë që ishte kujtesës adresën pc, çfarëdo karakteri ishte më parë atje, tani D, në qoftë se ne themi * PC = D. Pra, këtu ne do të shkojmë përsëri me disa sende çuditshme C, e drejtë. Pra, ne kemi parë * më parë si disi pjesë e tipit të të dhënave, dhe tani ajo është duke u përdorur në një kontekst pak më të ndryshme për të hyrë në të dhënat në një vend. Unë e di se është pak konfuze dhe kjo është në fakt pjesë e kësaj e tërë si, pse pointers kanë këtë mitologji rreth tyre si aq komplekse, është lloj i një problemi sintaksë, me ndershmëri. Por * është përdorur në të dy kontekstet, edhe si pjesë e emrit të tipit, dhe ne do të shohim pak diçka më vonë tjetër, too. Dhe tani është Operatori dereference. Pra, ajo shkon në referencë, ajo accesses të dhënat e në vendin e kursorit, dhe ju lejon për të manipuluar atë sipas dëshirës. Tani kjo është shumë e ngjashme me vizituar të afërmin tënd, e drejtë. Nëse ju e dini se çfarë tuaj fqinji jeton, ju jeni nuk varur me fqinjin tuaj. Ju e dini që ju ndodh që të e di se ku ata jetojnë, por kjo nuk do të thotë se nga virtyt i pasur këtë njohuri ju jeni të bashkëveprojmë me ta. Nëse ju doni për të bashkëvepruar me ta, ju duhet të shkoni në shtëpinë e tyre, ju duhet të shkoni për të ku ata jetojnë. Dhe një herë ju bëni këtë, atëherë ju mund të bashkëveprojnë me ta ashtu si ju do të duan të. Dhe në mënyrë të ngjashme me variablat, ju duhet të shkoni në adresën e tyre në qoftë se ju doni për të bashkëvepruar ato, ju nuk mund vetëm të dinë adresën. Dhe mënyra që ju të shkoni në adresën e është për të përdorur *, operatori dereference. Çfarë mendoni ju ndodh nëse ne përpiqemi dhe dereference një tregues vlera e të cilit është i pavlefshëm? Kujtojnë se null tregues tregon asgjë. Pra, nëse ju provoni dhe dereference asgjë ose shkoni në një asgjë adresën, çfarë mendoni ju ndodh? Segmentimit E pra në qoftë se ju mendoi faj, ju do të jetë e drejtë. Nëse ju provoni dhe dereference një tregues null, vuani një ndarje faji. Por prisni, nuk po ju them se në qoftë se ju nuk jeni duke shkuar për të vendosur vlerën tuaj e juaj tregues për diçka të rëndësishme, ju duhet të vënë të null? Kam bërë dhe në fakt segmentimit faji është lloj i një sjellje të mirë. A keni deklaruar ndonjëherë një ndryshore dhe Nuk caktuar vlerën e saj menjëherë? Kështu që ju vetëm të thonë int x; ju nuk e bëni në fakt të caktojë atë për ndonjë gjë dhe pastaj më vonë në kodin tuaj, ju shtypura nga vlera e x, nuk ka ende caktuar atë për ndonjë gjë. Shpesh ju do të merrni zero, por ndonjëherë ju mund të marrë disa numër të rastit, dhe ju nuk keni ide se ku ai erdhi nga. Në mënyrë të ngjashme mund të gjëra ndodhë me pointers. Kur ju të deklarojë një akrep int * pk për shembull, dhe ju nuk caktojë atë në një vlerë, ju merrni katër bytes për kujtesën. Çfarëdo katër bytes kujtesës sistemi mund gjeni se kanë disa vlera kuptimplotë. Dhe nuk mund të ketë qenë diçka tashmë atje që nuk është më e nevojshme nga një tjetër funksion, kështu që ju vetëm duhet çfarëdo të dhënave ishte atje. Çfarë ndodh nëse ju u përpoq të bëjë dereference disa adresa që ju don't- ka qenë tashmë bytes dhe informacioni në atje, kjo është tani në treguesin tuaj. Nëse ju provoni dhe dereference atë akrep, ju mund të messing me disa kujtesës që ju nuk e keni ndërmend të luajnë me të gjitha. Dhe në të vërtetë ju mund të bëni diçka me të vërtetë shkatërruese, si të thyer një tjetër program, ose të thyejnë një tjetër funksion, ose të bëjë diçka me qëllim të keq që ju nuk e keni ndërmend të bëni në të gjitha. Dhe kështu kjo është arsyeja pse kjo është në fakt një ide e mirë për të vendosur tuaj pointers për null nëse ju nuk i vendosur ato në diçka kuptimplotë. Kjo është ndoshta më të mirë në Fundi i ditës për programin tuaj të rrëzuar, atëherë për atë për të bërë Diçka që vida deri një program apo një tjetër funksion. Kjo sjellje është ndoshta edhe më pak se ideale vetëm crashing. Dhe kështu kjo është arsyeja pse kjo është në fakt një zakon i mirë për të marrë në për të vendosur tuaj pointers të null qoftë se ju nuk vendosur ato në një vlerë kuptimplotë menjëherë, një vlerë që ju të dini dhe që ju mund të sigurtë dereference. Pra, le të kthehem tani dhe për të marrë një vështrim në sintaksë e përgjithshëm të situatës. Nëse unë them int * p ;, Çfarë kam bërë vetëm? Ajo që unë kam bërë është kjo. Unë e di se vlera e p është një adresë sepse të gjitha pointers janë vetëm Adresat. Unë mund dereference p duke përdorur operatorin *. Në këtë kontekst këtu, në shumë lartë kujtojnë * është pjesë e tipit. Int * është lloji dhënave. Por unë mund të dereference p duke përdorur operatorin *, dhe në qoftë se unë bëj kështu, nëse unë shkoj në atë adresë, çfarë do të gjej në atë adresë? Unë do të gjeni një numër të plotë. Pra, int * p është në thelb duke thënë: p është një adresë. Unë mund dereference p dhe nëse Unë bëj, unë do të gjeni një numër të plotë në atë vend e kujtesës. OK kështu që unë tha se nuk ishte një tjetër gjë bezdisshëm me yje dhe këtu është ku që gjë bezdisshëm me yje është. A keni provuar ndonjëherë për të deklaruar variabla të shumta të të njëjtit lloj në të njëjtin drejtim të kodit? Pra, për një të dytë, të pretendojë se vija, kodi Unë në fakt kam atje në gjelbër nuk ka dhe vetëm ajo thotë int x, y, z ;. Çfarë kjo do të bëjë në fakt është të krijojë tre variabla numër i plotë për ju, një i quajtur X, një i quajtur y, dhe një quajtur z. Kjo është një mënyrë për të bërë atë pa pasur nevojë për të ndarë në tre rreshta. Ja ku yjet merrni bezdisshëm përsëri edhe pse, sepse * është në fakt pjesë të dy emrit tipit dhe pjesë e emrit ndryshueshme. Dhe kështu që nëse unë them int * px, py, PZ, çfarë unë në fakt të merrni është një tregues për një numër të plotë quajtur px dhe dy integers, py dhe PZ. Dhe kjo ndoshta nuk është çfarë ne duam, kjo nuk është e mirë. Pra, nëse unë dua të krijoj pointers të shumta në të njëjtën linjë, i llojit të njëjtë, dhe yjet, çfarë unë në fakt duhet të bëni është të themi int * PA, * BP, * pc. Tani ka thënë vetëm se dhe tani po ju them këtë, ju ndoshta kurrë nuk do ta bëjë këtë. Dhe kjo është ndoshta një gjë e mirë me ndershmëri, sepse ju mund pa dashje heq një yll, diçka të tillë. Kjo është ndoshta më e mirë për të ndoshta të deklaruar pointers në linja të veçanta, por kjo është vetëm një tjetër e atyre bezdisshëm sintaksë gjëra me yjet që e bëjnë pointers kaq e vështirë për të punuar me të. Për shkak se ajo është vetëm kjo sintaktik rrëmujë ju duhet të punojnë me. Me praktikë kjo e bën të vërtetë të bëhet natyrë e dytë. Unë ende bëjnë gabime me atë ende pas programimit për 10 vjet, kështu që nuk do të jetë mërzitur, nëse ndodh diçka për ju, kjo është goxha e përbashkët me ndershmëri. Është me të vërtetë lloji i një e metë e sintaksës. OK kështu që unë lloj i premtuar se ne do të rishqyrtojnë koncepti i se sa i madh është një varg. E pra, nëse unë ju tha se një string, ne kemi me të vërtetë lloji i është gënjyer për ju të gjithë kohën. Nuk ka asnjë lloj të dhënave të quajtur string, dhe në fakt unë përmendur këtë në një nga tonë më të hershme video në lloje të të dhënave, se string ishte një lloj të dhënave që është krijuar për ju në CS50.h. Ju duhet të #include CS50.h në mënyrë që të përdorin atë. E pra string është me të vërtetë vetëm një alias për diçka quhet char *, një tregues për një karakter. E pra pointers, kujtojnë, janë vetëm adreson. Pra, çfarë është madhësia në bytes i një varg? E pra kjo është katër ose tetë. Dhe arsyeja unë them katër ose tetë është për shkak se në fakt varet nga sistemi, Nëse jeni duke përdorur CS50 ide, char * është madhësia e një char * Është tetë, kjo është një sistem 64-bit. Çdo adresa në kujtesë është 64 bit e gjatë. Nëse jeni duke përdorur pajisjen CS50 ose duke përdorur ndonjë makinë 32-bit, dhe ju keni dëgjuar se gjatë 32-bit makine, çfarë është një makinë 32-bit? E pra kjo thjesht do të thotë se çdo Adresa në memorie është 32 bit e gjatë. Dhe kështu 32 bit është katër bytes. Pra, një char * është katër ose tetë bytes varësi të sistemit tuaj. Dhe me të vërtetë çdo lloj të të dhënave, dhe një tregues për ndonjë të dhënave lloji, pasi të gjitha pointers janë vetëm adresat, janë katër ose tetë bytes. Pra, le të rishqyrtojnë këtë diagramin dhe le të përfundojmë Kjo video me një stërvitje të vogël këtu. Kështu që këtu është diagrami ne e kemi lënë jashtë me në fillim të videos. Pra, çfarë ndodh tani, nëse unë them PK = 35 *? Pra, çfarë do të thotë kur unë them, * PK = 35? Merrni një të dytë. * pk. Në kontekst këtu, * është Operatori dereference. Kështu që kur dereference Operatori është përdorur, ne do të shkojmë në adresën vuri në dukje nga PK, dhe ne të ndryshojë atë që kemi gjetur. Pra PK = 35 * efektive e bën këtë në foto. Pra, kjo është në thelb sintaksore identike me të ka thënë k = 35. Nje me shume. Nëse unë them m int, unë krijoj një variabël të ri të quajtur m. Një kuti e re, kjo është një kuti e gjelbër për shkak se ajo do të mbajë një numër të plotë, dhe kjo është etiketuar m. Nëse unë them m = 4, kam vënë një numër i plotë në atë kuti. Nëse themi PK = & m, si e bën ky ndryshim diagram? PK = & M, a ju kujtohet se çfarë Dhe Operatori bën apo quhet? Mos harroni se & emërin e ndryshueshme është adresa e një emrin e ndryshueshme. Pra, ajo që ne jemi duke thënë është pk merr adresën e m. Dhe kështu në mënyrë efektive çfarë ndodh diagram është se pk pikë nuk është më për k, por tregon m. Përsëri pointers janë shumë ndërlikuar për të punuar me dhe ata e marrin shumë praktikë, por për shkak të aftësisë së tyre për të lejuar ju për të kaluar të dhënave në mes funksioneve të dhe në fakt kanë ata Ndryshimet hyjnë në fuqi, duke marrë kokën tuaj rreth është me të vërtetë e rëndësishme. Kjo ndoshta është më e komplikuar tema kemi diskutuar në CS50, por vlera që ju merrni nga përdorimi pointers tejkalon komplikacione që vijnë nga të mësuarit e tyre. Kështu që unë ju uroj më të mirë të fat mësuar rreth pointers. Unë jam Doug Lloyd, kjo është CS50.