1 00:00:00,000 --> 00:00:02,520 [Powered by Google Translate] [Secțiunea 4 - mai confortabil] 2 00:00:02,520 --> 00:00:04,850 [Rob Bowden - Universitatea Harvard] 3 00:00:04,850 --> 00:00:07,370 [Acest lucru este CS50. - CS50.TV] 4 00:00:08,920 --> 00:00:13,350 Avem un test mâine, în cazul în care voi nu știți că. 5 00:00:14,810 --> 00:00:20,970 E practic pe tot ce ai putut fi văzut în clasă sau ar fi văzut în clasă. 6 00:00:20,970 --> 00:00:26,360 Aceasta include indicii, chiar dacă ele sunt un subiect foarte recentă. 7 00:00:26,360 --> 00:00:29,860 Tu ar trebui cel puțin să înțeleagă niveluri ridicate ale acestora. 8 00:00:29,860 --> 00:00:34,760 Orice lucru care a fost plecat peste in clasa ar trebui să înțeleagă pentru test. 9 00:00:34,760 --> 00:00:37,320 Deci, dacă aveți întrebări cu privire la ele, le puteți întreba acum. 10 00:00:37,320 --> 00:00:43,280 Dar acest lucru va fi o sesiune foarte elev condusă de unde voi pune întrebări, 11 00:00:43,280 --> 00:00:45,060 deci sperăm că oamenii au întrebări. 12 00:00:45,060 --> 00:00:48,020 Are cineva întrebări? 13 00:00:49,770 --> 00:00:52,090 Da. >> [Elev] Poti sa te duci peste indicii din nou? 14 00:00:52,090 --> 00:00:54,350 Voi trece peste pointeri. 15 00:00:54,350 --> 00:00:59,180 Toate variabilele neapărat trăiesc în memorie, 16 00:00:59,180 --> 00:01:04,450 dar, de obicei, nu vă faceți griji despre asta și ai spus x si y + 2 + 3 17 00:01:04,450 --> 00:01:07,080 și compilatorul va da seama unde lucrurile sunt vii pentru tine. 18 00:01:07,080 --> 00:01:12,990 După ce de-a face cu pointeri, acum te utilizați în mod explicit acele adrese de memorie. 19 00:01:12,990 --> 00:01:19,800 Deci, o singură variabilă va fi doar trăi vreodată într-o singură adresă la un moment dat. 20 00:01:19,800 --> 00:01:24,040 Dacă vrem să declare un pointer, ceea ce este tipul de gând să arate? 21 00:01:24,040 --> 00:01:26,210 >> Vreau să declare un pointer p. Ce face tipul arata? 22 00:01:26,210 --> 00:01:33,530 [Elev] int * p. Da >>. Deci, int * p. 23 00:01:33,530 --> 00:01:38,030 Și cum să fac să indice către x? >> [Elev] Ampersand. 24 00:01:40,540 --> 00:01:45,300 [Bowden] Deci ampersand este literalmente numit adresa operatorului. 25 00:01:45,300 --> 00:01:50,460 Deci, atunci când spun & x se obține adresa de memorie a variabilei x. 26 00:01:50,460 --> 00:01:56,790 Asa ca acum am p indicatorul, și oriunde în codul meu pot folosi * p 27 00:01:56,790 --> 00:02:02,960 sau am putea folosi x si va fi exact același lucru. 28 00:02:02,960 --> 00:02:09,520 (* P). Ce este aceasta face? Ce înseamnă asta înseamnă stea? 29 00:02:09,520 --> 00:02:13,120 [Elev] Aceasta înseamnă o valoare în acel moment. Da >>. 30 00:02:13,120 --> 00:02:17,590 Deci, dacă ne uităm la ea, poate fi foarte util pentru a scoate în diagrame 31 00:02:17,590 --> 00:02:22,230 în cazul în care aceasta este o cutie mica de memorie pentru x, care se întâmplă să aibă valoarea 4, 32 00:02:22,230 --> 00:02:25,980 atunci avem o cutie mica de memorie pentru p, 33 00:02:25,980 --> 00:02:31,590 și astfel punctele p la x, asa ca am trage o săgeată de la P la x. 34 00:02:31,590 --> 00:02:40,270 Așa că atunci când spunem p * ne spui merge la caseta care este p. 35 00:02:40,270 --> 00:02:46,480 Star este urmați săgeată și apoi faci ce vrei cu cutia aia de acolo. 36 00:02:46,480 --> 00:03:01,090 Deci, eu pot spune * p = 7, și care va merge la caseta pe care este x și schimbare care la 7. 37 00:03:01,090 --> 00:03:13,540 Sau aș putea spune int z = * p * 2; Asta e confuz, deoarece stele, stele. 38 00:03:13,540 --> 00:03:19,230 De o stea este dereferencing p, alte stele este înmulțirea cu 2. 39 00:03:19,230 --> 00:03:26,780 Observati ca am putea avea la fel de bine înlocuiește p * cu x. 40 00:03:26,780 --> 00:03:29,430 Aveți posibilitatea să le utilizați în același mod. 41 00:03:29,430 --> 00:03:38,000 Și apoi mai târziu am pot avea p punctul de a un lucru complet nou. 42 00:03:38,000 --> 00:03:42,190 Eu pot spune doar p = &z; 43 00:03:42,190 --> 00:03:44,940 Deci, acum nu p puncte mai la X, aceasta subliniază la z. 44 00:03:44,940 --> 00:03:50,510 Și în orice moment să fac * p e la fel ca faci z. 45 00:03:50,510 --> 00:03:56,170 Deci, lucru util despre acest lucru este, odată ce vom începe a intra în funcțiile. 46 00:03:56,170 --> 00:03:59,790 >> E un fel de inutil să declare un pointer care indică spre ceva 47 00:03:59,790 --> 00:04:03,140 si apoi esti doar o dereferencing 48 00:04:03,140 --> 00:04:06,060 , atunci când ar fi putut folosi variabila originală pentru a începe cu. 49 00:04:06,060 --> 00:04:18,190 Dar atunci când vei ajunge în funcții - așa că hai să spunem că avem o anumită funcție, int foo, 50 00:04:18,190 --> 00:04:32,810 care ia un pointer și doar nu * p = 6; 51 00:04:32,810 --> 00:04:39,990 Cum am văzut înainte de swap cu, nu poți să faci un schimb eficient și o funcție separată 52 00:04:39,990 --> 00:04:45,180 prin care trece doar numere întregi pentru că totul în C este întotdeauna trece prin valoare. 53 00:04:45,180 --> 00:04:48,360 Chiar și atunci când ești trece indicii ce te trece prin valoare. 54 00:04:48,360 --> 00:04:51,940 Pur și simplu așa se întâmplă că aceste valori sunt adrese de memorie. 55 00:04:51,940 --> 00:05:00,770 Deci, atunci când spun foo (p); am trece indicatorul în funcția de foo 56 00:05:00,770 --> 00:05:03,910 si apoi foo este de a face * p = 6; 57 00:05:03,910 --> 00:05:08,600 Deci, în interiorul acestei funcții, * p este încă echivalent cu x, 58 00:05:08,600 --> 00:05:12,720 dar eu nu pot folosi x interiorul această funcție, deoarece nu e scoped în această funcție. 59 00:05:12,720 --> 00:05:19,510 Deci, * p = 6 este singurul mod pot accesa o variabilă locală dintr-o altă funcție. 60 00:05:19,510 --> 00:05:23,600 Sau, ei bine, pointerii sunt singurul mod pot accesa o variabilă locală dintr-o altă funcție. 61 00:05:23,600 --> 00:05:31,600 [Elev] Hai spune că a vrut să se întoarcă un pointer. Exact cum faci asta? 62 00:05:31,600 --> 00:05:44,270 [Bowden] Reveniți un indicator la fel ca în ceva de genul int y = 3; retur & Y? >> [Elev] Da. 63 00:05:44,270 --> 00:05:48,480 [Bowden] Ok. Tu nu ar trebui să facă acest lucru. Acest lucru este rău. 64 00:05:48,480 --> 00:05:59,480 Cred că am văzut în aceste diapozitive curs ai început să vezi această diagramă întreagă de memorie 65 00:05:59,480 --> 00:06:02,880 în cazul în care aici le-ați luat adresa de memorie 0 66 00:06:02,880 --> 00:06:09,550 si aici aveti adresa de memorie 4 gig-uri sau 2 pentru a 32. 67 00:06:09,550 --> 00:06:15,120 Deci, atunci ai niște lucruri și unele lucruri si apoi ai stack-ul 68 00:06:15,120 --> 00:06:21,780 și le-ați luat morman ta, pe care tocmai l-ați început să învețe despre, în creștere în sus. 69 00:06:21,780 --> 00:06:24,390 [Elev] nu este grămadă de mai sus stiva? 70 00:06:24,390 --> 00:06:27,760 >> Da. Heap este pe partea de sus, nu-i așa? >> [Elev] Ei bine, el a pus pe partea de sus 0. 71 00:06:27,760 --> 00:06:30,320 [Elev] Oh, el a pus pe partea de sus 0. >> [Elev] Oh, bine. 72 00:06:30,320 --> 00:06:36,060 Disclaimer: Oriunde, cu CS50 ai de gând să-l văd în acest fel. >> [Elev] Ok. 73 00:06:36,060 --> 00:06:40,290 E doar că, atunci când te vezi prima stive, 74 00:06:40,290 --> 00:06:45,000 ca atunci când te gândești la un teanc credeți de stivuire lucruri pe partea de sus a unul pe altul. 75 00:06:45,000 --> 00:06:50,810 Deci, avem tendinta de a răsturna această jurul astfel încât stiva este în creștere în sus ca o stivă în mod normal, ar fi 76 00:06:50,810 --> 00:06:55,940 în loc de stivă este purtata in jos. >> [Elev] Nu grămezi cresc punct de vedere tehnic prea, deși? 77 00:06:55,940 --> 00:07:01,100 Aceasta depinde de ceea ce vrei să spui cu maturizezi. 78 00:07:01,100 --> 00:07:04,010 Stivă și heap cresc întotdeauna în direcții opuse. 79 00:07:04,010 --> 00:07:09,420 O stivă este întotdeauna în creștere până în sensul că este în creștere în sus 80 00:07:09,420 --> 00:07:12,940 spre adrese mai mari de memorie, și heap este în creștere în jos 81 00:07:12,940 --> 00:07:17,260 în măsura în care este în creștere față de adresele de memorie mai mici. 82 00:07:17,260 --> 00:07:20,250 Deci, partea de sus este 0 și partea de jos este de adrese de memorie de mare. 83 00:07:20,250 --> 00:07:26,390 Sunt amândoi în creștere, doar în direcții opuse. 84 00:07:26,390 --> 00:07:29,230 [Elev] Am vrut doar că pentru că ai spus că ai pus teancul în partea de jos 85 00:07:29,230 --> 00:07:33,640 deoarece se pare mult mai intuitivă, deoarece pentru stiva să înceapă de la partea de sus a unui heap, 86 00:07:33,640 --> 00:07:37,520 morman e pe partea de sus de la sine, deci that - >> Da. 87 00:07:37,520 --> 00:07:44,960 Puteți, de asemenea că a heap ca de creștere și mai mare, dar stiva cu atât mai mult. 88 00:07:44,960 --> 00:07:50,280 Deci, stivă este cea pe care am cam vrea să arate crescut. 89 00:07:50,280 --> 00:07:55,390 Dar peste tot te uiti altfel va pentru a vedea adresa de 0 la partea de sus 90 00:07:55,390 --> 00:07:59,590 și adresa de memorie mai mare în partea de jos, astfel încât aceasta este opinia dumneavoastră obișnuită de memorie. 91 00:07:59,590 --> 00:08:02,100 >> Ai o intrebare? 92 00:08:02,100 --> 00:08:04,270 [Elev] Ne puteți spune mai multe despre heap? 93 00:08:04,270 --> 00:08:06,180 Da. Voi ajunge la faptul că într-o secundă. 94 00:08:06,180 --> 00:08:12,220 În primul rând, revenind la motivul pentru returnarea & y este un lucru rău, 95 00:08:12,220 --> 00:08:18,470 pe stiva aveți o grămadă de cadre stack care reprezintă toate funcțiile 96 00:08:18,470 --> 00:08:20,460 care au fost chemați. 97 00:08:20,460 --> 00:08:27,990 Deci, ignorând lucrurile anterioare, partea de sus a stack-ul tău este întotdeauna o să fie funcția principală 98 00:08:27,990 --> 00:08:33,090 din moment ce e prima funcție care a fost numit. 99 00:08:33,090 --> 00:08:37,130 Și apoi când apelați o altă funcție, stiva este de gând să crească în jos. 100 00:08:37,130 --> 00:08:41,640 Deci, dacă am numi o anumită funcție, foo, și devine cadrul acesteia stivă proprie, 101 00:08:41,640 --> 00:08:47,280 se poate apela o anumită funcție, bar, acesta devine rama stiva proprie. 102 00:08:47,280 --> 00:08:49,840 Și barul ar putea fi recursive și s-ar putea numi ea însăși, 103 00:08:49,840 --> 00:08:54,150 și astfel încât al doilea apel la Barul este mergi la a lua cadru de stivă proprie. 104 00:08:54,150 --> 00:08:58,880 Și astfel, ceea ce se întâmplă în aceste cadre stack sunt toate variabilele locale 105 00:08:58,880 --> 00:09:03,450 și toate argumentele funcției care - 106 00:09:03,450 --> 00:09:08,730 Orice lucruri care sunt la nivel local scoped la această funcție meargă în aceste cadre stack. 107 00:09:08,730 --> 00:09:21,520 Asta înseamnă că atunci când am zis ceva de genul bar este o funcție, 108 00:09:21,520 --> 00:09:29,270 Mă duc să declare un număr întreg și apoi să se întoarcă un pointer la întreg. 109 00:09:29,270 --> 00:09:33,790 Deci, în cazul în care nu locuiesc y? 110 00:09:33,790 --> 00:09:36,900 [Elev] Y locuiește în bar. >> [Bowden] Da. 111 00:09:36,900 --> 00:09:45,010 Undeva în acest pătrat mic de memorie este un pătrat Littler care are y în ea. 112 00:09:45,010 --> 00:09:53,370 Când mă voi întoarce & Y, Mă întorc un pointer la acest bloc mic de memorie. 113 00:09:53,370 --> 00:09:58,400 Dar apoi, când se întoarce funcția, rama stiva sa se apărut pe stiva. 114 00:10:01,050 --> 00:10:03,530 Și de aceea se numește stivă. 115 00:10:03,530 --> 00:10:06,570 E ca și cum structura de date stiva, dacă știi ce este. 116 00:10:06,570 --> 00:10:11,580 Sau chiar ca un teanc de tăvi este întotdeauna exemplu, 117 00:10:11,580 --> 00:10:16,060 principal este de gând să meargă pe partea de jos, apoi prima funcție suna este de gând să meargă pe partea de sus de faptul că, 118 00:10:16,060 --> 00:10:20,400 si nu poti sa ma intorc la principal până când te vei întoarce de la toate funcțiile care au fost numite 119 00:10:20,400 --> 00:10:22,340 care au fost plasate pe partea de sus a acesteia. 120 00:10:22,340 --> 00:10:28,650 >> [Elev] Deci, dacă tu ai făcut reveni y &, ca valoare este supusă de a schimba fără notificare prealabilă. 121 00:10:28,650 --> 00:10:31,290 Da, e. - >> [elev] Ar putea fi suprascrise. Da >>. 122 00:10:31,290 --> 00:10:34,660 E complet - Dacă încercați și - 123 00:10:34,660 --> 00:10:38,040 Acest lucru ar fi, de asemenea, un bar * int, deoarece se întoarce un pointer, 124 00:10:38,040 --> 00:10:41,310 deci tipul său de retur este * int. 125 00:10:41,310 --> 00:10:46,500 Dacă încercați să utilizați valoarea întoarsă de această funcție, e un comportament nedefinit 126 00:10:46,500 --> 00:10:51,770 pentru că indicatorul indică memorie proasta. >> [Elev] Ok. 127 00:10:51,770 --> 00:11:01,250 Și ce dacă, de exemplu, a declarat int * y = malloc (sizeof (int))? 128 00:11:01,250 --> 00:11:03,740 Asta e mai bine. Da. 129 00:11:03,740 --> 00:11:07,730 [Elev] Noi am vorbit despre cum, atunci când ne trageți lucrurile să coșul de gunoi nostru 130 00:11:07,730 --> 00:11:11,750 ei nu sunt de fapt șterse; vom pierde doar pointeri lor. 131 00:11:11,750 --> 00:11:15,550 Deci, în acest caz, avem de fapt șterge valoarea sau este încă acolo, în memoria? 132 00:11:15,550 --> 00:11:19,130 Pentru cea mai mare parte, o să fie încă acolo. 133 00:11:19,130 --> 00:11:24,220 Dar hai să spunem că se întâmplă pentru a apela o alta functie, Baz. 134 00:11:24,220 --> 00:11:28,990 Baz este mergi la a lua cadru de stivă propria aici. 135 00:11:28,990 --> 00:11:31,470 O să fie suprascrierea toate aceste lucruri, 136 00:11:31,470 --> 00:11:34,180 și apoi, dacă încercați mai târziu și de a folosi indicatorul pe care ai înainte, 137 00:11:34,180 --> 00:11:35,570 nu va fi aceeași valoare. 138 00:11:35,570 --> 00:11:38,150 Se va fi schimbat doar pentru că ai sunat Baz funcția. 139 00:11:38,150 --> 00:11:43,080 [Elev] Dar dacă nu am fi, ne-am primi în continuare 3? 140 00:11:43,080 --> 00:11:44,990 [Bowden] În toate probabilitățile, ai face. 141 00:11:44,990 --> 00:11:49,670 Dar nu te poti baza pe asta. C spune doar un comportament nedefinit. 142 00:11:49,670 --> 00:11:51,920 >> [Elev] Oh, nu. Bine. 143 00:11:51,920 --> 00:11:58,190 Deci, atunci când doriți să se întoarcă un pointer, în cazul în care acest lucru este malloc vine în uz. 144 00:12:00,930 --> 00:12:15,960 Am scris, de fapt a reveni la doar malloc (3 * sizeof (int)). 145 00:12:17,360 --> 00:12:24,050 Vom trece peste malloc mai mult intr-o secunda, dar ideea de malloc este tot de variabilele locale 146 00:12:24,050 --> 00:12:26,760 întotdeauna merge pe stiva. 147 00:12:26,760 --> 00:12:31,570 Orice lucru care se malloced merge pe movila, și-l va pentru totdeauna și să fie întotdeauna pe heap 148 00:12:31,570 --> 00:12:34,490 până când eliberați în mod explicit. 149 00:12:34,490 --> 00:12:42,130 Deci, acest lucru înseamnă că, atunci când malloc ceva, o să supraviețuiască după întoarcerea funcția. 150 00:12:42,130 --> 00:12:46,800 [Elev] Va supraviețui după programul de funcționare se oprește? Nu >> 151 00:12:46,800 --> 00:12:53,180 Bine, așa că va fi acolo pana cand programul este tot drumul făcut de rulare. Da >>. 152 00:12:53,180 --> 00:12:57,510 Putem merge peste detalii cu privire la ceea ce se întâmplă atunci când rulează programul se oprește. 153 00:12:57,510 --> 00:13:02,150 S-ar putea nevoie pentru a-mi aminti, dar că este un lucru separat în întregime. 154 00:13:02,150 --> 00:13:04,190 [Elev] Deci, malloc creează un pointer? Da >>. 155 00:13:04,190 --> 00:13:13,030 Malloc - >> [elev] Cred că malloc desemnează un bloc de memorie pe care un pointer poate folosi. 156 00:13:15,400 --> 00:13:19,610 [Bowden] Vreau diagrama din nou. >> [Elev] Deci, această funcție este, totuși? 157 00:13:19,610 --> 00:13:26,430 [Elev] Da, malloc desemnează un bloc de memorie pe care le puteți utiliza, 158 00:13:26,430 --> 00:13:30,470 și apoi returnează adresa primului bloc de memorie care. 159 00:13:30,470 --> 00:13:36,750 >> [Bowden] Da. Deci, atunci când malloc, te hapsân unele bloc de memorie 160 00:13:36,750 --> 00:13:38,260 care este în prezent în grămadă. 161 00:13:38,260 --> 00:13:43,040 În cazul în heap este prea mic, atunci heap este doar de gând să crească, și aceasta crește în această direcție. 162 00:13:43,040 --> 00:13:44,650 Deci, haideți să spunem heap este prea mic. 163 00:13:44,650 --> 00:13:49,960 Apoi este vorba despre să crească un pic și a reveni un pointer la acest bloc, care tocmai au crescut. 164 00:13:49,960 --> 00:13:55,130 Când chestii gratuite, tu faci mai mult spațiu în heap, 165 00:13:55,130 --> 00:14:00,030 Deci, atunci o sun mai târziu la malloc poate reutiliza că memoria pe care le-au eliberat anterior. 166 00:14:00,030 --> 00:14:09,950 Cel mai important lucru despre malloc și gratuit este că vă oferă control complet 167 00:14:09,950 --> 00:14:12,700 peste durata de viață a acestor blocuri de memorie. 168 00:14:12,700 --> 00:14:15,420 Variabilele globale sunt mereu vie. 169 00:14:15,420 --> 00:14:18,500 Variabilele locale sunt în viață în domeniul de aplicare a acestora. 170 00:14:18,500 --> 00:14:22,140 De îndată ce te duci trecut o proteză cret, variabilele locale sunt morți. 171 00:14:22,140 --> 00:14:28,890 Memoria Malloced este în viață când vrei să fii în viață 172 00:14:28,890 --> 00:14:33,480 și apoi este eliberat atunci când îl spui să fie eliberat. 173 00:14:33,480 --> 00:14:38,420 Acestea sunt, de fapt, doar 3 tipuri de memorie, într-adevăr. 174 00:14:38,420 --> 00:14:41,840 Nu e de management automat al memoriei, care este stiva. 175 00:14:41,840 --> 00:14:43,840 Lucrurile se întâmplă pentru tine în mod automat. 176 00:14:43,840 --> 00:14:46,910 Când spui x int, memoria este alocată pentru x int. 177 00:14:46,910 --> 00:14:51,630 Atunci când x iese din sfera de aplicare, memorie este regenerată pentru x. 178 00:14:51,630 --> 00:14:54,790 Apoi, nu e de management al memoriei dinamice, care este ceea ce este malloc, 179 00:14:54,790 --> 00:14:56,740 care este atunci când aveți de control. 180 00:14:56,740 --> 00:15:01,290 Tu decizi dinamic atunci când memoria ar trebui să și nu ar trebui să fie alocate. 181 00:15:01,290 --> 00:15:05,050 Și apoi nu e static, ceea ce înseamnă doar că trăiește pentru totdeauna, 182 00:15:05,050 --> 00:15:06,610 care este ceea ce variabilele globale sunt. 183 00:15:06,610 --> 00:15:10,240 Sunt doar mereu în memorie. 184 00:15:10,960 --> 00:15:12,760 >> Întrebări? 185 00:15:14,490 --> 00:15:17,230 [Elev] Poți defini un bloc doar prin utilizarea acolade 186 00:15:17,230 --> 00:15:21,220 dar care nu au de a avea o? if sau o declarație vreme sau ceva de genul asta 187 00:15:21,220 --> 00:15:29,130 Puteți defini un bloc ca într-o funcție, dar care are acolade prea. 188 00:15:29,130 --> 00:15:32,100 [Elev] Deci, nu poti avea la fel ca o pereche de acolade aleatoriu în codul dvs. 189 00:15:32,100 --> 00:15:35,680 care au variabilele locale? >> Da, puteți. 190 00:15:35,680 --> 00:15:45,900 În interiorul barei de int am putea avea {int y = 3;}. 191 00:15:45,900 --> 00:15:48,440 Asta ar trebui să fie chiar aici. 192 00:15:48,440 --> 00:15:52,450 Dar care definește complet domeniul de aplicare al int y. 193 00:15:52,450 --> 00:15:57,320 După aceea bretele două cret, y nu poate fi folosit mai. 194 00:15:57,910 --> 00:16:00,630 Ai aproape niciodată asta, deși. 195 00:16:02,940 --> 00:16:07,370 Noțiuni de bază înapoi la ceea ce se întâmplă atunci când un program se termină, 196 00:16:07,370 --> 00:16:18,760 e un fel de minciună neînțelegere / jumătate dăm, în scopul de a face doar lucrurile mai ușor. 197 00:16:18,760 --> 00:16:24,410 Noi vă spunem că, atunci când aloca memorie 198 00:16:24,410 --> 00:16:29,860 te alocarea unei părți bucată de RAM pentru acea variabilă. 199 00:16:29,860 --> 00:16:34,190 Dar tu nu ești cu adevărat atingă direct RAM vreodată în programele dumneavoastră. 200 00:16:34,190 --> 00:16:37,490 Dacă te gândești la asta, cum am desenat - 201 00:16:37,490 --> 00:16:44,330 Și, de fapt, dacă te duci prin GDB în veți vedea același lucru. 202 00:16:51,120 --> 00:16:57,590 Indiferent de câte ori aveți o de program sau de ce program ai rulează, 203 00:16:57,590 --> 00:16:59,950 stiva este întotdeauna de gând să înceapă - 204 00:16:59,950 --> 00:17:06,510 mereu te duci sa vezi variabile în jurul a ceva oxbffff adresa. 205 00:17:06,510 --> 00:17:09,470 Este, de obicei, undeva în acea regiune. 206 00:17:09,470 --> 00:17:18,760 Dar cum poate avea, eventual, 2 programe indicatori către aceeași memorie? 207 00:17:20,640 --> 00:17:27,650 [Elev] E un desemnarea arbitrar de locul în care oxbfff ar trebui să fie pe memoria RAM 208 00:17:27,650 --> 00:17:31,320 care poate fi de fapt în locuri diferite, în funcție de momentul în care funcția a fost numit. 209 00:17:31,320 --> 00:17:35,920 Da. Termenul este memoria virtuală. 210 00:17:35,920 --> 00:17:42,250 Ideea este că fiecare proces unic, fiecare singur program care se execută pe computer 211 00:17:42,250 --> 00:17:49,450 are propriul său - să presupunem 32 de biți - spațiu de adrese complet independent. 212 00:17:49,450 --> 00:17:51,590 Acesta este spațiul de adrese. 213 00:17:51,590 --> 00:17:56,220 Ea are propriile sale complet independente 4 gigaocteți de a utiliza. 214 00:17:56,220 --> 00:18:02,220 >> Deci, dacă aveți 2 programe simultan, acest program vede 4 gigaocteți la sine, 215 00:18:02,220 --> 00:18:04,870 acest program vede 4 gigaocteți la sine, 216 00:18:04,870 --> 00:18:07,720 și este imposibil pentru acest program pentru a dereference un pointer 217 00:18:07,720 --> 00:18:10,920 și se încheie cu o memorie de la acest program. 218 00:18:10,920 --> 00:18:18,200 Și ce memorie virtuală este o mapare de la un spațiu de adrese procese 219 00:18:18,200 --> 00:18:20,470 la lucruri reale pe RAM. 220 00:18:20,470 --> 00:18:22,940 Deci, este de până la sistemul de operare să știe că, 221 00:18:22,940 --> 00:18:28,080 hei, atunci când acest tip oxbfff dereferences indicatorul, care înseamnă cu adevărat 222 00:18:28,080 --> 00:18:31,040 că el vrea RAM octet 1000, 223 00:18:31,040 --> 00:18:38,150 întrucât în ​​cazul în care acest program oxbfff dereferences, el vrea cu adevărat RAM octet 10000. 224 00:18:38,150 --> 00:18:41,590 Ele pot fi arbitrar departe unul de altul. 225 00:18:41,590 --> 00:18:48,730 Acest lucru este adevărat și de lucruri într-un singur spațiu adrese procese. 226 00:18:48,730 --> 00:18:54,770 Deci, la fel ca el vede toate cele 4 gigaocteți la sine, dar hai sa spunem - 227 00:18:54,770 --> 00:18:57,290 [Elev] Are fiecare singur proces - 228 00:18:57,290 --> 00:19:01,350 Să presupunem că aveți un calculator cu numai 4 GB de RAM. 229 00:19:01,350 --> 00:19:06,430 Are fiecare proces unic vedea întregul 4 gigaocteți? Da >>. 230 00:19:06,430 --> 00:19:13,060 Dar ea vede 4 gigaocteți este o minciună. 231 00:19:13,060 --> 00:19:20,460 E doar crede că are toate astea de memorie pentru că nu cunosc nici un alt proces există. 232 00:19:20,460 --> 00:19:28,140 Se vor folosi numai de memorie la fel de mult ca de fapt are nevoie. 233 00:19:28,140 --> 00:19:32,340 Sistemul de operare nu este de gând să dea RAM la acest proces 234 00:19:32,340 --> 00:19:35,750 în cazul în care nu se folosește nici o amintire în întreaga regiune. 235 00:19:35,750 --> 00:19:39,300 Aceasta nu va da de memorie pentru această regiune. 236 00:19:39,300 --> 00:19:54,780 Dar ideea este că - Încerc să mă gândesc la - Nu mă pot gândi la o analogie. 237 00:19:54,780 --> 00:19:56,780 Analogii sunt greu. 238 00:19:57,740 --> 00:20:02,700 Una din problemele de memorie virtuală sau unul dintre lucrurile pe care le-a rezolvare 239 00:20:02,700 --> 00:20:06,810 este faptul că procesele ar trebui să fie complet conștienți de una de alta. 240 00:20:06,810 --> 00:20:12,140 Și astfel încât să puteți scrie orice program care dereferences orice fel de pointer, 241 00:20:12,140 --> 00:20:19,340 ca scrie doar un program care spune * (ox1234), 242 00:20:19,340 --> 00:20:22,890 adresa și faptul că memoria dereferencing 1234. 243 00:20:22,890 --> 00:20:28,870 >> Dar este de până la sistemul de operare pentru a traduce apoi ce înseamnă 1234. 244 00:20:28,870 --> 00:20:33,960 Deci, dacă se întâmplă să fie 1234 o adresă de memorie validă pentru acest proces, 245 00:20:33,960 --> 00:20:38,800 ca e pe stivă sau ceva, atunci acest lucru se va returna valoarea de care adresei de memorie 246 00:20:38,800 --> 00:20:41,960 în ceea ce privește procesul de știe. 247 00:20:41,960 --> 00:20:47,520 Dar dacă nu este 1234 o adresă validă, se întâmplă ca să aterizeze 248 00:20:47,520 --> 00:20:52,910 în unele mică bucată de memorie aici, care este dincolo de stivă și dincolo de heap 249 00:20:52,910 --> 00:20:57,200 și nu ați folosit într-adevăr că, atunci asta e atunci când ajungi lucruri, cum ar fi segfaults 250 00:20:57,200 --> 00:21:00,260 pentru ca esti atingi de memorie pe care nu ar trebui să fie ating. 251 00:21:07,180 --> 00:21:09,340 Acest lucru este, de asemenea, adevărat - 252 00:21:09,340 --> 00:21:15,440 Un sistem pe 32 de biți, 32 de biți înseamnă că trebuie 32 de biți pentru a defini o adresă de memorie. 253 00:21:15,440 --> 00:21:22,970 Acesta este motivul pentru indicii sunt 8 octeți, deoarece 32 de biți sunt 8 octeți sau 4 octeți -. 254 00:21:22,970 --> 00:21:25,250 Pointeri sunt 4 octeți. 255 00:21:25,250 --> 00:21:33,680 Deci, când veți vedea un indicator ca oxbfffff, care este - 256 00:21:33,680 --> 00:21:40,080 În cadrul oricărui program de dat poti construi orice fel de indicatorul arbitrară, 257 00:21:40,080 --> 00:21:46,330 oriunde de la ox0 la ox 8 f's - ffffffff. 258 00:21:46,330 --> 00:21:49,180 [Elev] N-ai spus că sunt 4 octeți? Da >>. 259 00:21:49,180 --> 00:21:52,730 [Elev] Apoi, fiecare octet va avea - >> [Bowden] Hexadecimal. 260 00:21:52,730 --> 00:21:59,360 Hexadecimal - 5, 6, 7, 8. Deci, indicii veti vedea mereu în hexazecimal. 261 00:21:59,360 --> 00:22:01,710 E doar modul în care ne clasifica pointeri. 262 00:22:01,710 --> 00:22:05,240 La fiecare 2 cifre ale hexazecimal este de 1 octet. 263 00:22:05,240 --> 00:22:09,600 Deci nu va fi de 8 cifre hexazecimale pentru 4 octeți. 264 00:22:09,600 --> 00:22:14,190 Deci, la fiecare indicatorul singur pe un sistem de 32-biți va fi 4 octeți, 265 00:22:14,190 --> 00:22:18,550 ceea ce înseamnă că, în procesul de dumneavoastră, puteți construi orice arbitrare 4 octeți 266 00:22:18,550 --> 00:22:20,550 și să facă un pointer din ea, 267 00:22:20,550 --> 00:22:32,730 ceea ce înseamnă că, în măsura în care acesta este conștient, se poate adresa unui întreg 2 la 32 bytes de memorie. 268 00:22:32,730 --> 00:22:34,760 Chiar dacă nu are cu adevărat acces la faptul că, 269 00:22:34,760 --> 00:22:40,190 chiar dacă computerul tău are doar 512 MB, acesta crede că are acea memorie de mult. 270 00:22:40,190 --> 00:22:44,930 Și sistemul de operare este suficient de inteligent ca va aloca doar ceea ce ai de fapt nevoie. 271 00:22:44,930 --> 00:22:49,630 Ea nu merge doar, oh, un nou proces: 4 show-uri. 272 00:22:49,630 --> 00:22:51,930 >> Da. >> [Elev] Ce bou înseamnă? De ce ai scris-o? 273 00:22:51,930 --> 00:22:54,980 E doar simbolul pentru hexazecimal. 274 00:22:54,980 --> 00:22:59,590 Când vedeți un început număr cu boul, lucrurile sunt succesive hexazecimal. 275 00:23:01,930 --> 00:23:05,760 [Elev] Ai fost să explice despre ce se întâmplă atunci când un program se termină. Da >>. 276 00:23:05,760 --> 00:23:09,480 Ce se întâmplă atunci când un program se termină este sistemul de operare 277 00:23:09,480 --> 00:23:13,600 șterge doar mapările pe care le are pentru aceste adrese, și asta e tot. 278 00:23:13,600 --> 00:23:17,770 Sistemul de operare poate oferi acum doar că memoria la un alt program pentru a utiliza. 279 00:23:17,770 --> 00:23:19,490 [Elev] Ok. 280 00:23:19,490 --> 00:23:24,800 Deci, atunci când alocă ceva pe halde sau variabilele stivei sau globale sau orice altceva, 281 00:23:24,800 --> 00:23:27,010 acestea toate dispar la fel de repede ca și programul se încheie 282 00:23:27,010 --> 00:23:32,120 deoarece sistemul de operare este acum gratuit pentru a da ca memoria oricărui alt proces. 283 00:23:32,120 --> 00:23:35,150 [Elev] Chiar dacă există, probabil, încă valori scrise în? Da >>. 284 00:23:35,150 --> 00:23:37,740 Valorile sunt probabil încă acolo. 285 00:23:37,740 --> 00:23:41,570 E doar că va fi dificil pentru a ajunge la ele. 286 00:23:41,570 --> 00:23:45,230 E mult mai greu pentru a ajunge la ei decât este de a ajunge la un fișier șters 287 00:23:45,230 --> 00:23:51,450 deoarece tipul de fișier șters sta acolo pentru o lungă perioadă de timp și unitatea hard disk este mult mai mare. 288 00:23:51,450 --> 00:23:54,120 Deci, o să suprascrie diferite părți ale memoriei 289 00:23:54,120 --> 00:23:58,640 înainte de a se întâmplă să suprascrie bucată de memorie pe care acel fișier folosit pentru a fi la. 290 00:23:58,640 --> 00:24:04,520 Dar memoria principală, RAM, ai ciclului printr-o mult mai repede, 291 00:24:04,520 --> 00:24:08,040 așa că va fi suprascrise foarte rapid. 292 00:24:10,300 --> 00:24:13,340 Întrebări cu privire la acest lucru sau orice altceva? 293 00:24:13,340 --> 00:24:16,130 [Elev] Am întrebări despre un subiect diferit. Bine >>. 294 00:24:16,130 --> 00:24:19,060 Are cineva întrebări cu privire la acest lucru? 295 00:24:20,170 --> 00:24:23,120 >> Bine. Diferite subiect. >> [Elev] Ok. 296 00:24:23,120 --> 00:24:26,550 Am fost trece prin unele dintre teste de practică, 297 00:24:26,550 --> 00:24:30,480 și într-una dintre ele a fost vorba despre sizeof 298 00:24:30,480 --> 00:24:35,630 și valoarea pe care returnează sau diferite tipuri de variabile. Da >>. 299 00:24:35,630 --> 00:24:45,060 Și a spus că atât timp cât int si retur 4, astfel încât acestea sunt atât lungimea de 4 octeți. 300 00:24:45,060 --> 00:24:48,070 Există vreo diferență între un int și un lung, sau este același lucru? 301 00:24:48,070 --> 00:24:50,380 Da, există o diferență. 302 00:24:50,380 --> 00:24:52,960 Standard C - 303 00:24:52,960 --> 00:24:54,950 Am, probabil, de gând să încurce. 304 00:24:54,950 --> 00:24:58,800 Standardul C este la fel ca ceea ce C este, documentația oficială a lui C. 305 00:24:58,800 --> 00:25:00,340 Aceasta este ceea ce se spune. 306 00:25:00,340 --> 00:25:08,650 Deci, standardul C spune doar că o va char pentru totdeauna și întotdeauna să fie de 1 octet. 307 00:25:10,470 --> 00:25:19,040 Totul după care - o scurtă este întotdeauna la fel definită ca fiind mai mare sau egal cu un char. 308 00:25:19,040 --> 00:25:23,010 Acest lucru ar putea fi strict mai mare decât, dar nu pozitivă. 309 00:25:23,010 --> 00:25:31,940 Un int este la fel definită ca fiind mai mare sau egală cu un scurtcircuit. 310 00:25:31,940 --> 00:25:36,210 Și un lung este la fel definită ca fiind mai mare sau egală cu un int. 311 00:25:36,210 --> 00:25:41,600 Și o lungă lung este mai mare sau egală cu un lung. 312 00:25:41,600 --> 00:25:46,610 Deci, singurul lucru standard C defineste este ordonarea relativă a tot. 313 00:25:46,610 --> 00:25:54,880 Cantitatea reală de memorie ca lucrurile să ia sus este, în general, până la punerea în aplicare, 314 00:25:54,880 --> 00:25:57,640 dar e destul de bine definit în acest moment. >> [Elev] Ok. 315 00:25:57,640 --> 00:26:02,490 Deci, pantaloni scurți sunt aproape întotdeauna o să fie de 2 octeți. 316 00:26:04,920 --> 00:26:09,950 Ints sunt aproape întotdeauna o să fie de 4 octeți. 317 00:26:12,070 --> 00:26:15,340 Lungimi lungi sunt aproape întotdeauna o să fi de 8 octeți. 318 00:26:17,990 --> 00:26:23,160 Și dorește, depinde dacă utilizați un 32-bit sau un sistem de 64-biți. 319 00:26:23,160 --> 00:26:27,450 Deci, un lung este de gând să corespundă cu tipul de sistem. 320 00:26:27,450 --> 00:26:31,920 Dacă utilizați un sistem pe 32 de biți ca Aparatura, o să fie de 4 octeți. 321 00:26:34,530 --> 00:26:42,570 Dacă utilizați un 64-biți ca o mulțime de calculatoare recente, o să fi de 8 octeți. 322 00:26:42,570 --> 00:26:45,230 >> Ints sunt aproape intotdeauna 4 octeți de la acest punct. 323 00:26:45,230 --> 00:26:47,140 Lungimi lungi sunt aproape întotdeauna 8 octeți. 324 00:26:47,140 --> 00:26:50,300 În trecut, Ints folosit pentru a fi doar 2 octeți. 325 00:26:50,300 --> 00:26:56,840 Dar observați că acest îndeplinește complet toate aceste relații de mai mare și egal cu. 326 00:26:56,840 --> 00:27:01,280 Atât de mult timp este perfect permis să fie de aceeași dimensiune ca un întreg, 327 00:27:01,280 --> 00:27:04,030 și este, de asemenea, a permis să fie de aceeași dimensiune ca un lung timp. 328 00:27:04,030 --> 00:27:11,070 Și doar așa se întâmplă să fie că, în 99,999% din sisteme, aceasta va fi egală cu 329 00:27:11,070 --> 00:27:15,800 fie un int sau un lung timp. Este doar depinde de 32-biți sau 64-biți. >> [Elev] Ok. 330 00:27:15,800 --> 00:27:24,600 În flotoare, cât este punctul zecimal desemnat în termeni de biți? 331 00:27:24,600 --> 00:27:27,160 Dori ca un binar? Da >>. 332 00:27:27,160 --> 00:27:30,570 Nu aveți nevoie să știe că pentru CS50. 333 00:27:30,570 --> 00:27:32,960 Tu nu invata chiar că, în 61. 334 00:27:32,960 --> 00:27:37,350 Tu nu invata că într-adevăr, în orice curs. 335 00:27:37,350 --> 00:27:42,740 E doar o reprezentare. 336 00:27:42,740 --> 00:27:45,440 Am uitat de alocații exacte biți. 337 00:27:45,440 --> 00:27:53,380 Ideea de virgulă mobilă pe care îl alocă un anumit număr de biți pentru a reprezenta - 338 00:27:53,380 --> 00:27:56,550 Practic, totul este în notație științifică. 339 00:27:56,550 --> 00:28:05,600 Astfel încât să aloce un anumit număr de biți pentru a reprezenta numărul însuși, ca și 1.2345. 340 00:28:05,600 --> 00:28:10,200 Eu nu pot reprezenta un număr cu cifre mai mult de 5. 341 00:28:12,200 --> 00:28:26,300 Apoi, va aloca, de asemenea, un anumit număr de biți, astfel încât acesta tinde să fie ca 342 00:28:26,300 --> 00:28:32,810 poti sa te duci numai până la un anumit număr, cum ar fi faptul că e cel mai mare exponent poti avea, 343 00:28:32,810 --> 00:28:36,190 și puteți merge doar până la un anumit exponent, 344 00:28:36,190 --> 00:28:38,770 ca asta e cel mai mic exponent poti avea. 345 00:28:38,770 --> 00:28:44,410 >> Nu-mi aduc aminte de biți exacte modul în care sunt alocate pentru toate aceste valori, 346 00:28:44,410 --> 00:28:47,940 dar un anumit număr de biți sunt dedicate 1.2345, 347 00:28:47,940 --> 00:28:50,930 un alt anumit număr de biți sunt dedicate exponent, 348 00:28:50,930 --> 00:28:55,670 și este posibil să reprezinte un exponent de o anumită dimensiune. 349 00:28:55,670 --> 00:29:01,100 [Elev] Și o dublă? Este ca ca un flotor extra lung? Da >>. 350 00:29:01,100 --> 00:29:07,940 E același lucru ca un float, cu excepția acum sunteți folosind 8 octeți în loc de 4 octeți. 351 00:29:07,940 --> 00:29:11,960 Acum vei putea folosi 9 cifre sau 10 cifre, 352 00:29:11,960 --> 00:29:16,630 iar acest lucru va fi capabil să meargă până la 300 în loc de 100. >> [Elev] Ok. 353 00:29:16,630 --> 00:29:21,550 Și plutește sunt, de asemenea, 4 octeți. Da >>. 354 00:29:21,550 --> 00:29:27,520 Ei bine, din nou, probabil depinde de ansamblu privind punerea în aplicare generală, 355 00:29:27,520 --> 00:29:30,610 dar flotoare sunt 4 octeți, camere duble sunt de 8. 356 00:29:30,610 --> 00:29:33,440 Duble sunt numite dublu, deoarece acestea sunt duble dimensiunea de flotoare. 357 00:29:33,440 --> 00:29:38,380 [Elev] Ok. Și acolo sunt dublu dublu? Nu sunt >>. 358 00:29:38,380 --> 00:29:43,660 Cred că - >> [elev] Ca lungimi lungi? Da >>. Nu sunt de părere. Da. 359 00:29:43,660 --> 00:29:45,950 [Elev] La testul de anul trecut a existat o întrebare despre funcția principală 360 00:29:45,950 --> 00:29:49,490 având în a fi parte a programului dumneavoastră. 361 00:29:49,490 --> 00:29:52,310 Răspunsul a fost că nu trebuie să facă parte din programul dumneavoastră. 362 00:29:52,310 --> 00:29:55,100 În ce situație? Asta e ceea ce am văzut. 363 00:29:55,100 --> 00:29:59,090 [Bowden] Se pare - >> [elev] Ce situație? 364 00:29:59,090 --> 00:30:02,880 Ai probleme? >> [Elev] Da, eu pot trage cu siguranta-l în sus. 365 00:30:02,880 --> 00:30:07,910 Aceasta nu trebuie să fie, punct de vedere tehnic, dar în esență o să fie. 366 00:30:07,910 --> 00:30:10,030 [Elev] Am văzut una pe un an diferit de. 367 00:30:10,030 --> 00:30:16,220 A fost ca și cum Adevarat sau Fals: O validă - >> Oh, un c fisier.? 368 00:30:16,220 --> 00:30:18,790 . [Elev] Orice fișier c trebuie să aibă - [vorbind, atât dintr-o dată - de neînțeles] 369 00:30:18,790 --> 00:30:21,120 Bine. Deci asta e separat. 370 00:30:21,120 --> 00:30:26,800 >> Un fișier C. Trebuie doar să conțină funcții. 371 00:30:26,800 --> 00:30:32,400 Puteți compila un fișier în cod mașină, binar, indiferent, 372 00:30:32,400 --> 00:30:36,620 fără a fi încă executabil. 373 00:30:36,620 --> 00:30:39,420 Un executabil validă trebuie să aibă o funcție principală. 374 00:30:39,420 --> 00:30:45,460 Puteți scrie 100 de funcții în 1 fisier dar nu principalelor 375 00:30:45,460 --> 00:30:48,800 și apoi compila că până la binar, 376 00:30:48,800 --> 00:30:54,460 atunci va scrie un alt fișier care are doar principal, dar solicită o grămadă de aceste funcții 377 00:30:54,460 --> 00:30:56,720 în acest fișier binar de aici. 378 00:30:56,720 --> 00:31:01,240 Și așa că atunci când faci executabil, asta e ceea ce face linker-ul 379 00:31:01,240 --> 00:31:05,960 se combină aceste 2 fișiere binare într-un executabil. 380 00:31:05,960 --> 00:31:11,400 Deci, un fișier c.., Nu are nevoie să aibă o funcție principală, la toate. 381 00:31:11,400 --> 00:31:19,220 Și pe baze de cod mari, veți vedea mii de fișiere. C și 1 fișierul principal. 382 00:31:23,960 --> 00:31:26,110 Mai multe întrebări? 383 00:31:29,310 --> 00:31:31,940 [Elev] Nu a fost o altă întrebare. 384 00:31:31,940 --> 00:31:36,710 Acesta a declarat fac este un compilator. Adevărat sau fals? 385 00:31:36,710 --> 00:31:42,030 Și răspunsul a fost fals, și am înțeles de ce nu e ca zăngănit. 386 00:31:42,030 --> 00:31:44,770 Dar ce numim face dacă nu e? 387 00:31:44,770 --> 00:31:49,990 Asigurați-este de fapt doar - Eu pot vedea exact ceea ce se solicită. 388 00:31:49,990 --> 00:31:52,410 Dar se execută doar comenzile. 389 00:31:53,650 --> 00:31:55,650 Asigurați. 390 00:31:58,240 --> 00:32:00,870 Pot trage asta. Da. 391 00:32:10,110 --> 00:32:13,180 Oh, da. Asigurați-are, de asemenea, faptul că. 392 00:32:13,180 --> 00:32:17,170 Aceasta spune scopul de a marca de utilitate este de a determina în mod automat 393 00:32:17,170 --> 00:32:19,610 care bucăți de un program de mare trebuie să fie recompilate 394 00:32:19,610 --> 00:32:22,350 și emite comenzi pentru a le recompilați. 395 00:32:22,350 --> 00:32:27,690 Puteți face face fișierele care sunt absolut imens. 396 00:32:27,690 --> 00:32:33,210 Asigurați uită la ștampilele de timp de fișiere și, așa cum am spus mai înainte, 397 00:32:33,210 --> 00:32:36,930 puteți compila fișierele individuale în jos, și nu e până când ajunge la linker-ul 398 00:32:36,930 --> 00:32:39,270 că acestea sunt puse împreună într-un executabil. 399 00:32:39,270 --> 00:32:43,810 Deci, dacă aveți 10 fișiere diferite și faceți o schimbare la 1 din ele, 400 00:32:43,810 --> 00:32:47,870 atunci ceea ce fac este de gând să faci este doar faptul că recompilare 1 fișier 401 00:32:47,870 --> 00:32:50,640 și repună în legătură apoi totul împreună. 402 00:32:50,640 --> 00:32:53,020 Dar e mult mai prost decât asta. 403 00:32:53,020 --> 00:32:55,690 E de până la tine pentru a defini complet că e ceea ce ar trebui să facă. 404 00:32:55,690 --> 00:32:59,560 Ea implicit are capacitatea de a recunoaste aceste lucruri ștampila de timp, 405 00:32:59,560 --> 00:33:03,220 dar aveți posibilitatea să scrie un fișier marcă să facă ceva. 406 00:33:03,220 --> 00:33:09,150 Puteți scrie un fișier face astfel încât atunci când tastați face doar CD-uri într-un alt director. 407 00:33:09,150 --> 00:33:15,560 Am fost obtinerea frustrat pentru că am tot ce tac interiorul Aparatura meu 408 00:33:15,560 --> 00:33:21,740 si apoi am vedea PDF din Mac. 409 00:33:21,740 --> 00:33:30,720 >> Așa că mă duc la Finder și eu pot să fac Du-te, Conectare la server, 410 00:33:30,720 --> 00:33:36,950 și să mă conectez la serverul de e Appliance meu, iar apoi am deschide PDF- 411 00:33:36,950 --> 00:33:40,190 care devine compilate de LaTeX. 412 00:33:40,190 --> 00:33:49,320 Dar am fost obtinerea frustrat deoarece de fiecare data am avut nevoie pentru a actualiza PDF, 413 00:33:49,320 --> 00:33:53,900 A trebuit să-l copiați într-un anumit director, care ar putea avea acces 414 00:33:53,900 --> 00:33:57,710 și a fost obtinerea enervant. 415 00:33:57,710 --> 00:34:02,650 Deci, în loc am scris un fișier marcă, care va trebui să definiți modul în care face lucrurile. 416 00:34:02,650 --> 00:34:06,130 Cum te face în acest sens este PDF LaTeX. 417 00:34:06,130 --> 00:34:10,090 La fel ca orice alt fișier face alte - sau cred că nu s-au văzut dosarele faceti-va, 418 00:34:10,090 --> 00:34:13,510 dar avem în Aparatura un fișier marca la nivel mondial, care tocmai spune, 419 00:34:13,510 --> 00:34:16,679 Dacă compilați un fișier C, utilizați zăngănit. 420 00:34:16,679 --> 00:34:20,960 Și astfel, aici, în dosarul meu marca pe care o fac eu spun, 421 00:34:20,960 --> 00:34:25,020 acest fișier ai de gând să doriți să compilați cu PDF LaTeX. 422 00:34:25,020 --> 00:34:27,889 Și așa e LaTeX PDF care face compilare. 423 00:34:27,889 --> 00:34:31,880 Asigurați nu este compilarea. E doar execută aceste comenzi în ordinea I, specificată. 424 00:34:31,880 --> 00:34:36,110 Deci ruleaza LaTeX PDF, îl copiază directorul vreau să fie copiat la, 425 00:34:36,110 --> 00:34:38,270 este CD-uri la director și face alte lucruri, 426 00:34:38,270 --> 00:34:42,380 dar tot ce face este să recunoască atunci când un fișier modificări, 427 00:34:42,380 --> 00:34:45,489 și în cazul în care se schimbă, atunci acesta va rula comenzile pe care ar trebui sa ruleze 428 00:34:45,489 --> 00:34:48,760 atunci când se schimbă de fișiere. >> [Elev] Ok. 429 00:34:50,510 --> 00:34:54,420 Nu știu unde fișierele sunt globale faceti-va pentru mine sa-l verific. 430 00:34:57,210 --> 00:35:04,290 Alte întrebări? Orice din trecut teste? Orice pointer lucruri? 431 00:35:06,200 --> 00:35:08,730 Momentan nu sunt lucruri subtile, cum ar fi indicii cu - 432 00:35:08,730 --> 00:35:10,220 Eu nu am de gând să fie în măsură să găsească o întrebare test pe ea - 433 00:35:10,220 --> 00:35:16,250 dar la fel ca acest gen de lucruri. 434 00:35:19,680 --> 00:35:24,060 Asigurați-vă că ați înțeles că atunci când spun int * x * y - 435 00:35:24,890 --> 00:35:28,130 Acest lucru nu este exact nimic aici, cred. 436 00:35:28,130 --> 00:35:32,140 Dar, ca * x * y, cele 2 variabile sunt care sunt pe stiva. 437 00:35:32,140 --> 00:35:37,220 Când spun x = malloc (sizeof (int)), x este încă o variabilă pe stivă, 438 00:35:37,220 --> 00:35:41,180 malloc este un bloc de peste grămadă în, și avem x punct la grămadă. 439 00:35:41,180 --> 00:35:43,900 >> Deci ceva cu privire la punctele stivă la grămadă. 440 00:35:43,900 --> 00:35:48,100 Ori de câte ori te malloc ceva, te stocarea inevitabil în interiorul unui pointer. 441 00:35:48,100 --> 00:35:55,940 Așa că indicatorul este pe stiva, bloc malloced este pe heap. 442 00:35:55,940 --> 00:36:01,240 O mulțime de oameni se confuz și spune int * x = malloc; x este pe heap. 443 00:36:01,240 --> 00:36:04,100 Nu, ce indică spre x este pe heap. 444 00:36:04,100 --> 00:36:08,540 x în sine este pe stiva, cu excepția cazului în orice motiv ați x fi o variabilă globală, 445 00:36:08,540 --> 00:36:11,960 caz în care se întâmplă să fie într-o altă regiune de memorie. 446 00:36:13,450 --> 00:36:20,820 Deci păstrarea evidenței, aceste diagrame cutie și săgeata sunt destul de comune pentru test. 447 00:36:20,820 --> 00:36:25,740 Sau dacă nu e pe test 0, acesta va fi pe test 1. 448 00:36:27,570 --> 00:36:31,940 Ar trebui să știi toate acestea, pașii din compilarea 449 00:36:31,940 --> 00:36:35,740 din moment ce a trebuit să răspundă la întrebări privind cele. Da. 450 00:36:35,740 --> 00:36:38,940 [Elev] Putem trece peste aceste etape - >> Sigur. 451 00:36:48,340 --> 00:36:58,640 Înainte de a pasi si compilarea avem preprocesare, 452 00:36:58,640 --> 00:37:16,750 compilarea, asamblarea și legarea. 453 00:37:16,750 --> 00:37:21,480 Preprocesare. Ce face asta? 454 00:37:29,720 --> 00:37:32,290 Acesta este cel mai simplu pas în - ei bine, nu ca - 455 00:37:32,290 --> 00:37:35,770 asta nu inseamna ca ar trebui sa fie evident, dar e cel mai simplu pas. 456 00:37:35,770 --> 00:37:38,410 Voi putea implementa voi înșivă. Da. 457 00:37:38,410 --> 00:37:43,410 [Elev] Ia ceea ce aveți în dvs. include ca acest lucru și-l copiază și apoi, de asemenea, definește. 458 00:37:43,410 --> 00:37:49,250 Se pare că pentru lucruri cum ar fi: # include # define și, 459 00:37:49,250 --> 00:37:53,800 și doar copii și paste ceea ce înseamnă de fapt cele. 460 00:37:53,800 --> 00:37:59,240 Deci, atunci când spui include # cs50.h, preprocesor este copierea și lipirea cs50.h 461 00:37:59,240 --> 00:38:01,030 în acea linie. 462 00:38:01,030 --> 00:38:06,640 Când spui # define x pentru a fi 4, preprocesor trece prin întregul program 463 00:38:06,640 --> 00:38:10,400 și înlocuiește toate cazurile de x cu 4. 464 00:38:10,400 --> 00:38:17,530 Deci, preprocesor ia un fișier C valabil și scoate un fișier valid C 465 00:38:17,530 --> 00:38:20,300 în cazul în care lucrurile au fost copiate și lipite. 466 00:38:20,300 --> 00:38:24,230 Deci, acum compilarea. Ce face asta? 467 00:38:25,940 --> 00:38:28,210 [Elev] Se merge de la C la binar. 468 00:38:28,210 --> 00:38:30,970 >> [Bowden] Nu merge tot drumul până la binar. 469 00:38:30,970 --> 00:38:34,220 [Elev] Pentru cod mașină, atunci? >> Nu e cod mașină. 470 00:38:34,220 --> 00:38:35,700 [Elev] Adunarea? Adunarea >>. 471 00:38:35,700 --> 00:38:38,890 Se merge la Adunarea înainte de a merge tot drumul la codul C, 472 00:38:38,890 --> 00:38:45,010 și cele mai multe limbi face ceva de genul asta. 473 00:38:47,740 --> 00:38:50,590 Alege orice limbaj de nivel înalt, și dacă ai de gând să-l compilați, 474 00:38:50,590 --> 00:38:52,390 este posibil să compilați în trepte. 475 00:38:52,390 --> 00:38:58,140 În primul rând se va compila Python la C, apoi se va compila C la Adunarea, 476 00:38:58,140 --> 00:39:01,600 și apoi Adunarea urmeaza sa se traduse în binar. 477 00:39:01,600 --> 00:39:07,800 Deci, compilarea se gând să-l aducă de la C la Adunarea. 478 00:39:07,800 --> 00:39:12,130 Cuvântul înseamnă, de obicei compilarea aducând-o la un nivel superior 479 00:39:12,130 --> 00:39:14,340 la un nivel mai mic limbaj de programare. 480 00:39:14,340 --> 00:39:19,190 Deci, acesta este singurul pas în elaborarea în cazul în care vă începeți cu un limbaj de nivel înalt 481 00:39:19,190 --> 00:39:23,270 și sfârșesc într-o limbă de nivel scăzut, și de aceea se numește pas compilarea. 482 00:39:25,280 --> 00:39:33,370 [Elev] În timpul compilării, să spunem că ați făcut # include cs50.h. 483 00:39:33,370 --> 00:39:42,190 Va compilatorul recompilare cs50.h, cum ar fi funcțiile care sunt acolo, 484 00:39:42,190 --> 00:39:45,280 și traduce asta în cod de asamblare, precum și, 485 00:39:45,280 --> 00:39:50,830 sau va copia și lipi ceva care a fost pre-Adunarea? 486 00:39:50,830 --> 00:39:56,910 cs50.h va destul de mult niciodata nu se termina pana in Adunarea. 487 00:39:59,740 --> 00:40:03,680 Chestii de genul prototipuri funcționale și de lucruri sunt doar pentru tine de a fi atent. 488 00:40:03,680 --> 00:40:09,270 Se garantează că compilatorul poate verifica lucruri ca și cum ai de asteptare funcții 489 00:40:09,270 --> 00:40:12,910 cu tipurile potrivite de returnare, precum și argumentele potrivite si alte chestii. 490 00:40:12,910 --> 00:40:18,350 >> Deci, cs50.h va fi preprocesată în fișier, și apoi atunci când este compilarea 491 00:40:18,350 --> 00:40:22,310 Este practic aruncate după ce se asigură că totul se numește în mod corect. 492 00:40:22,310 --> 00:40:29,410 Dar funcțiile definite în biblioteca CS50, care sunt separate de cs50.h, 493 00:40:29,410 --> 00:40:33,610 cei care nu vor fi compilate separat. 494 00:40:33,610 --> 00:40:37,270 Care va veni de fapt, în etapa de legătură, așa că vom ajunge la faptul că într-o secundă. 495 00:40:37,270 --> 00:40:40,100 Dar, mai întâi, ceea ce este asamblarea? 496 00:40:41,850 --> 00:40:44,500 [Elev] Adunarea în binar? Da >>. 497 00:40:46,300 --> 00:40:48,190 Asamblarea. 498 00:40:48,190 --> 00:40:54,710 Noi nu spunem că compilarea Adunarea este destul de mult o traducere pură a binar. 499 00:40:54,710 --> 00:41:00,230 Există o logică foarte puțin în trecerea de la Adunarea în binar. 500 00:41:00,230 --> 00:41:03,180 E la fel ca uita în sus într-un tabel, oh, avem această instrucțiune; 501 00:41:03,180 --> 00:41:06,290 care corespunde binar 01110. 502 00:41:10,200 --> 00:41:15,230 Și astfel, fișierele pe care, în general, asamblarea ieșiri sunt. Fișiere o. 503 00:41:15,230 --> 00:41:19,020 Și fișierele sunt o. Ceea ce spuneam înainte, 504 00:41:19,020 --> 00:41:21,570 modul în care un fișier nu trebuie să aibă o funcție principală. 505 00:41:21,570 --> 00:41:27,640 Orice fișier poate fi compilat în jos într-un fișier. O, atâta timp cât este un fișier valid C. 506 00:41:27,640 --> 00:41:30,300 Acesta poate fi compilate în jos pentru a. O. 507 00:41:30,300 --> 00:41:43,030 Acum, legătura între ceea ce este de fapt aduce o grămadă de fișiere și o. Le aduce la un executabil. 508 00:41:43,030 --> 00:41:51,110 Și ce face linking este vă puteți gândi la bibliotecă CS50 ca un fișier. O. 509 00:41:51,110 --> 00:41:56,980 Acesta este un fișier binar compilat deja. 510 00:41:56,980 --> 00:42:03,530 Și așa, atunci când compilați fișierul, hello.c dumneavoastră, prin care se solicită getString, 511 00:42:03,530 --> 00:42:06,360 hello.c este compilată în jos pentru a hello.o, 512 00:42:06,360 --> 00:42:08,910 hello.o este acum în binar. 513 00:42:08,910 --> 00:42:12,830 Acesta utilizează getString, așa că trebuie să meargă pe la cs50.o, 514 00:42:12,830 --> 00:42:16,390 și linker-le împreună și smooshes copiaza getString în acest fișier 515 00:42:16,390 --> 00:42:20,640 și vine cu un executabil care are toate functiile de care are nevoie. 516 00:42:20,640 --> 00:42:32,620 Deci cs50.o nu este de fapt un fișier O, dar e destul de aproape că nu există nicio diferență fundamentală. 517 00:42:32,620 --> 00:42:36,880 Deci, care leagă doar aduce o grămadă de fișiere împreună 518 00:42:36,880 --> 00:42:41,390 care conțin separat toate funcțiile am nevoie pentru a utiliza 519 00:42:41,390 --> 00:42:46,120 și creează executabil care va rula, de fapt. 520 00:42:48,420 --> 00:42:50,780 >> Și, de asemenea, astfel încât ceea ce spuneam înainte 521 00:42:50,780 --> 00:42:55,970 unde poti avea 1000. fișiere c, te compilați-le pe toate la fișiere o,. 522 00:42:55,970 --> 00:43:00,040 care va avea, probabil, un timp, apoi modificați 1. fisierul c. 523 00:43:00,040 --> 00:43:05,480 Trebuie doar să recompilați că: 1. Dosarul C și apoi totul altceva relegarea, 524 00:43:05,480 --> 00:43:07,690 link totul înapoi împreună. 525 00:43:09,580 --> 00:43:11,430 [Elev] Atunci când suntem legătura între scriem lcs50? 526 00:43:11,430 --> 00:43:20,510 Da, așa-lcs50. Că semnalele de pavilion pentru a linker-ul pe care ar trebui să fie de legătură în acea bibliotecă. 527 00:43:26,680 --> 00:43:28,910 Întrebări? 528 00:43:41,310 --> 00:43:46,860 Am trecut peste binare, altele decât faptul că 5 secunde în prima prelegere? 529 00:43:50,130 --> 00:43:53,010 Nu sunt de părere. 530 00:43:55,530 --> 00:43:58,820 Ar trebui să știi toate Os mari pe care le-am trecut peste, 531 00:43:58,820 --> 00:44:02,670 și ar trebui să fie în măsură să, dacă am dat o funcție, 532 00:44:02,670 --> 00:44:09,410 ar trebui să fie în măsură să spun că e mare O, aproximativ. Sau bine, Big O e dur. 533 00:44:09,410 --> 00:44:15,300 Deci, dacă vedeți imbricate pentru bucle looping peste același număr de lucruri, 534 00:44:15,300 --> 00:44:22,260 cum ar fi int i, i > [elev] n pătrat. >> Acesta tinde să fie n pătrat. 535 00:44:22,260 --> 00:44:25,280 Dacă ați triplu imbricate, acesta tinde să fie n tocati. 536 00:44:25,280 --> 00:44:29,330 Deci, acest fel de lucru ar trebui să fie în măsură să sublinieze imediat. 537 00:44:29,330 --> 00:44:33,890 Ai nevoie să știi de inserție și sortare sortare cu bule și îmbinarea fel și toate cele. 538 00:44:33,890 --> 00:44:41,420 E mai ușor de înțeles de ce ei sunt cei n pătrat și n log n si toate că 539 00:44:41,420 --> 00:44:47,810 pentru că eu cred că a fost un test pe un an, dacă ne-ați dat practic 540 00:44:47,810 --> 00:44:55,050 o punere în aplicare de sortare cu bule și a spus, "Care este timpul de execuție al acestei funcții?" 541 00:44:55,050 --> 00:45:01,020 Așa că, dacă-l recunoaște ca un fel bule, atunci vă pot spune imediat n pătrat. 542 00:45:01,020 --> 00:45:05,470 Dar daca te uiti doar la el, nu aveți nevoie chiar de a realiza un fel e balon; 543 00:45:05,470 --> 00:45:08,990 vă pot spune doar acest face asta și asta. Acest lucru este n pătrat. 544 00:45:12,350 --> 00:45:14,710 [Elev] Există exemple dure puteți veni cu, 545 00:45:14,710 --> 00:45:20,370 ca o idee similară a imaginind? 546 00:45:20,370 --> 00:45:24,450 >> Nu cred că ne-ar da vreun exemplu dure. 547 00:45:24,450 --> 00:45:30,180 Lucru de sortare cu bule este la fel de dur ca ne-ar merge, 548 00:45:30,180 --> 00:45:36,280 și chiar faptul că, atâta timp cât ați înțeles că sunteți iterarea peste matrice 549 00:45:36,280 --> 00:45:41,670 pentru fiecare element în matrice, care va fi ceva care n pătrat. 550 00:45:45,370 --> 00:45:49,940 Există întrebări generale, cum ar fi chiar aici pe care le avem - Oh. 551 00:45:55,290 --> 00:45:58,530 Doar zilele trecute, Doug a afirmat: "Eu am inventat un algoritm care poate sorta o matrice 552 00:45:58,530 --> 00:46:01,780 "De numere n in O (log n) timp!" 553 00:46:01,780 --> 00:46:04,900 Deci, cum putem ști că e imposibil? 554 00:46:04,900 --> 00:46:08,850 [Răspuns studentul nu pot fi auzite] >> Da. 555 00:46:08,850 --> 00:46:13,710 Cel puțin, trebuie să atingeți fiecare element în matrice, 556 00:46:13,710 --> 00:46:16,210 așa că este imposibil să sortați o matrice de - 557 00:46:16,210 --> 00:46:20,850 Dacă totul este în ordine nesortate, atunci ai de gând să fie totul în atingerea matrice, 558 00:46:20,850 --> 00:46:25,320 astfel încât este imposibil de a face acest lucru în mai puțin de O din nr. 559 00:46:27,430 --> 00:46:30,340 [Elev] Sunteti ne-a arătat că exemplul de a fi capabil să-l facă în O de n 560 00:46:30,340 --> 00:46:33,920 dacă utilizați o mulțime de memorie. Da >>. 561 00:46:33,920 --> 00:46:37,970 Asta e. Și - am uitat ce that - Este un fel de numărare? 562 00:46:47,360 --> 00:46:51,330 Hmm. Acesta este un algoritm de sortare întreg. 563 00:46:59,850 --> 00:47:05,100 Am fost în căutarea pentru nume special pentru aceasta că nu am putut aminti săptămâna trecută. 564 00:47:05,100 --> 00:47:13,000 Da. Acestea sunt tipurile de felul, care pot realiza lucruri în mare O de n. 565 00:47:13,000 --> 00:47:18,430 Dar există limitări, ca tine se poate folosi numai numere întregi până la un anumit număr. 566 00:47:20,870 --> 00:47:24,560 Plus, dacă sunteți încercarea de a sorta that ceva - 567 00:47:24,560 --> 00:47:30,750 Dacă matricea este 012, -12, 151, 4 milioane de euro, 568 00:47:30,750 --> 00:47:35,120 apoi faptul că un singur element este de gând să strice totul de sortare intreaga. 569 00:47:42,060 --> 00:47:44,030 >> Întrebări? 570 00:47:49,480 --> 00:47:58,870 [Elev] Dacă aveți o funcție recursivă și-l face doar apeluri recursive 571 00:47:58,870 --> 00:48:02,230 într-o declarație retur, asta e coada recursiv, 572 00:48:02,230 --> 00:48:07,360 și astfel nu s-ar folosi mai multă memorie, care în timpul rulării 573 00:48:07,360 --> 00:48:12,550 sau ar folosi de memorie de cel puțin comparabilă ca un proces iterativ soluție? 574 00:48:12,550 --> 00:48:14,530 [Bowden] Da. 575 00:48:14,530 --> 00:48:19,840 Ar fi probabil ceva mai lent, dar nu chiar. 576 00:48:19,840 --> 00:48:23,290 Coada recursiv este destul de bun. 577 00:48:23,290 --> 00:48:32,640 Privind din nou la coșul de fum de cadre, să spunem că avem principal 578 00:48:32,640 --> 00:48:42,920 și ne-am int bar (int x) sau ceva. 579 00:48:42,920 --> 00:48:52,310 Aceasta nu este o funcție recursivă perfectă, dar bara de retur (x - 1). 580 00:48:52,310 --> 00:48:57,620 Deci, evident, acest lucru este greșit. Ai nevoie de cazuri de bază și alte chestii. 581 00:48:57,620 --> 00:49:00,360 Dar ideea aici este că acest lucru este coada recursiv, 582 00:49:00,360 --> 00:49:06,020 ceea ce înseamnă că atunci când solicită principal de bar se va obține cadrul său stivă. 583 00:49:09,550 --> 00:49:12,440 În acest cadru stiva acolo va fi un bloc mic de memorie 584 00:49:12,440 --> 00:49:17,490 care corespunde cu x argumentul său. 585 00:49:17,490 --> 00:49:25,840 Și așa că hai să spunem principal se întâmplă pentru a apela bar (100); 586 00:49:25,840 --> 00:49:30,050 Deci x este de gând să înceapă ca 100. 587 00:49:30,050 --> 00:49:35,660 În cazul în care compilatorul recunoaște că aceasta este o funcție recursivă coada, 588 00:49:35,660 --> 00:49:38,540 atunci când bara face apelul recursiv pentru a bloca, 589 00:49:38,540 --> 00:49:45,490 în loc de a face un cadru nou teanc, care este în cazul în care stiva incepe sa creasca mare măsură, 590 00:49:45,490 --> 00:49:48,220 în cele din urmă acesta va rula în grămadă și apoi te segfaults 591 00:49:48,220 --> 00:49:51,590 deoarece memoria începe coliziunea. 592 00:49:51,590 --> 00:49:54,830 >> Deci, în loc de a face cadrului său stiva proprie, se poate realiza, 593 00:49:54,830 --> 00:49:59,080 hei, n-am nevoie să vină înapoi la acest cadru stivă, 594 00:49:59,080 --> 00:50:08,040 astfel încât în ​​loc voi înlocui doar acest argument, cu 99 și apoi începe peste tot barul. 595 00:50:08,040 --> 00:50:11,810 Și apoi îl va face din nou și se va ajunge la bara de retur (x - 1), 596 00:50:11,810 --> 00:50:17,320 și în loc de a face un cadru nou teanc, acesta va înlocui pur și simplu argumentul său actual cu 98 597 00:50:17,320 --> 00:50:20,740 și apoi să sară înapoi la începutul bar. 598 00:50:23,860 --> 00:50:30,430 Aceste operațiuni, care înlocuiește valoarea 1 pe stivă și sărind înapoi la început, 599 00:50:30,430 --> 00:50:32,430 sunt destul de eficiente. 600 00:50:32,430 --> 00:50:41,500 Deci, nu numai ca aceasta este utilizarea memoriei ca o funcție separată, care este iterativ 601 00:50:41,500 --> 00:50:45,390 pentru că sunteți folosind doar 1 cadru stivă, dar tu nu ești suferă dezavantaje 602 00:50:45,390 --> 00:50:47,240 de a avea pentru a apela funcțiile. 603 00:50:47,240 --> 00:50:50,240 Funcțiile de asteptare poate fi oarecum costisitoare, deoarece are de a face toate acestea de configurare 604 00:50:50,240 --> 00:50:52,470 și teardown și toate chestiile astea. 605 00:50:52,470 --> 00:50:58,160 Deci, acest recursia Coada este bine. 606 00:50:58,160 --> 00:51:01,170 [Elev] De ce nu-l creează noi pași? 607 00:51:01,170 --> 00:51:02,980 Pentru că își dă seama că nu are nevoie să. 608 00:51:02,980 --> 00:51:07,800 Apel la barul se întoarce doar apelul recursiv. 609 00:51:07,800 --> 00:51:12,220 Deci nu are nevoie de a face ceva cu valoarea de returnare. 610 00:51:12,220 --> 00:51:15,120 E doar de gând să se întoarcă imediat. 611 00:51:15,120 --> 00:51:20,530 Deci, este doar de gând să înlocuiască argumentul său propriu și de la capăt. 612 00:51:20,530 --> 00:51:25,780 Și, de asemenea, în cazul în care nu aveți versiunea coada recursiv, 613 00:51:25,780 --> 00:51:31,460 atunci veți obține toate aceste baruri, unde atunci când această bară se întoarce 614 00:51:31,460 --> 00:51:36,010 ea are să se întoarcă valoarea sa la aceasta, atunci acel bar revine imediat 615 00:51:36,010 --> 00:51:39,620 și-l întoarce valoarea sa la aceasta, atunci e doar de gând să se întoarcă imediat 616 00:51:39,620 --> 00:51:41,350 și a reveni la valoarea sa aceasta. 617 00:51:41,350 --> 00:51:45,350 Deci, tu ești salvarea acestui popping toate aceste lucruri de pe stivă 618 00:51:45,350 --> 00:51:48,730 deoarece valoarea returnata este doar de gând să fi trecut tot drumul înapoi în sus, oricum. 619 00:51:48,730 --> 00:51:55,400 Deci, de ce nu doar înlocuiți argumentul nostru cu argumentul completa și începe peste? 620 00:51:57,460 --> 00:52:01,150 Dacă funcția nu este coada recursiv, dacă faci ceva de genul - 621 00:52:01,150 --> 00:52:07,530 [Elev] în cazul în care bara de (x + 1). Da >>. 622 00:52:07,530 --> 00:52:11,770 >> Deci, dacă ai pus-o în stare, atunci faci ceva cu valoarea de returnare. 623 00:52:11,770 --> 00:52:16,260 Sau chiar daca ai face doar retur 2 * bar (x - 1). 624 00:52:16,260 --> 00:52:23,560 Deci, acum, bar (x - 1) trebuie să se întoarcă pentru ca aceasta a calcula de 2 ori această valoare, 625 00:52:23,560 --> 00:52:26,140 asa ca acum ea are nevoie de ei cadru de propria stivă separată, 626 00:52:26,140 --> 00:52:31,180 și acum, indiferent de cat de greu incercati, ai de gând să nevoie pentru a - 627 00:52:31,180 --> 00:52:34,410 Acest lucru nu este coada recursiv. 628 00:52:34,410 --> 00:52:37,590 [Elev] Mi-ar încerca să aducă o recursivitate să vizeze o recursivitate coadă - 629 00:52:37,590 --> 00:52:41,450 [Bowden] Într-o lume ideală, dar în CS50 nu trebuie să. 630 00:52:43,780 --> 00:52:49,280 În scopul de a obține recursivitate coadă, în general, vă configurați un argument suplimentar 631 00:52:49,280 --> 00:52:53,550 în cazul în care bara va lua x int y în 632 00:52:53,550 --> 00:52:56,990 și Y corespunde lucru final pe care doriți să se întoarcă. 633 00:52:56,990 --> 00:53:03,650 Deci, atunci acest lucru ai de gând să fie returnarea bar (x - 1), 2 * y. 634 00:53:03,650 --> 00:53:09,810 Așa că e doar un nivel înalt cum te transformi lucrurile să fie coada recursiv. 635 00:53:09,810 --> 00:53:13,790 Dar argument în plus - 636 00:53:13,790 --> 00:53:17,410 Și apoi în cele din urmă, atunci când ajunge la cazul dumneavoastră de bază, vă întoarceți doar y 637 00:53:17,410 --> 00:53:22,740 pentru că ați fost acumularea tot timpul valoarea de returnare pe care o doriți. 638 00:53:22,740 --> 00:53:27,280 Ai un fel de au fost o fac iterativ, dar folosind apeluri recursive. 639 00:53:32,510 --> 00:53:34,900 Întrebări? 640 00:53:34,900 --> 00:53:39,890 [Elev] Poate despre aritmetică indicatorul, cum ar fi atunci când se utilizează șiruri. Sigur >>. 641 00:53:39,890 --> 00:53:43,610 Pointer aritmetică. 642 00:53:43,610 --> 00:53:48,440 Când utilizați șiruri e ușor pentru că sunt siruri de caractere char stele, 643 00:53:48,440 --> 00:53:51,860 caractere sunt pentru totdeauna și întotdeauna un singur octet, 644 00:53:51,860 --> 00:53:57,540 și așa aritmetică indicatorul este echivalent cu aritmetica regulat atunci când ai de a face cu siruri de caractere. 645 00:53:57,540 --> 00:54:08,790 Să spunem doar char * s = "Hello". 646 00:54:08,790 --> 00:54:11,430 Deci, avem un bloc în memorie. 647 00:54:19,490 --> 00:54:22,380 Este nevoie de 6 octeți, deoarece intotdeauna ai nevoie de terminator null. 648 00:54:22,380 --> 00:54:28,620 Și char * s este de gând să indice începutul acestei matrice. 649 00:54:28,620 --> 00:54:32,830 Deci Puncte acolo. 650 00:54:32,830 --> 00:54:36,710 Acum, acest lucru este practic modul în care funcționează orice matrice, 651 00:54:36,710 --> 00:54:40,780 indiferent dacă a fost o întoarcere de malloc sau dacă e pe stivă. 652 00:54:40,780 --> 00:54:47,110 Orice matrice este de fapt un pointer la începutul matrice, 653 00:54:47,110 --> 00:54:53,640 și apoi orice operațiune matrice, orice indexare, este doar de gând în această matrice un anumit offset. 654 00:54:53,640 --> 00:55:05,360 >> Asa ca atunci cand spun ceva de genul s [3], acest lucru este de gând să s și numărarea 3 caractere inch 655 00:55:05,360 --> 00:55:12,490 Deci, s [3], avem 0, 1, 2, 3, deci s [3] este de gând să se referă la acest l.. 656 00:55:12,490 --> 00:55:20,460 [Elev] Și am putea ajunge la aceeași valoare de a face S + 3 stele din paranteze și apoi? 657 00:55:20,460 --> 00:55:22,570 Da. 658 00:55:22,570 --> 00:55:26,010 Acest lucru este echivalent cu * (e + 3); 659 00:55:26,010 --> 00:55:31,240 și că este pentru totdeauna și întotdeauna echivalente, indiferent de ceea ce faci. 660 00:55:31,240 --> 00:55:34,070 Niciodată nu trebuie să utilizați sintaxa consola. 661 00:55:34,070 --> 00:55:37,770 Aveți posibilitatea să utilizați întotdeauna * (e + 3) sintaxă. 662 00:55:37,770 --> 00:55:40,180 Oamenii au tendința de a dori sintaxa suportul, totuși. 663 00:55:40,180 --> 00:55:43,860 [Elev] Deci, toate matricele sunt de fapt doar indicii. 664 00:55:43,860 --> 00:55:53,630 Există o distincție ușoară atunci când spun int x [4]; >> [elevului] nu creeze că memoria? 665 00:55:53,630 --> 00:56:03,320 [Bowden], care este de gând să creeze 4 Ints pe stiva, deci 16 bytes de ansamblu. 666 00:56:03,320 --> 00:56:05,700 Se va crea 16 bytes pe stiva. 667 00:56:05,700 --> 00:56:09,190 x nu este stocat nicăieri. 668 00:56:09,190 --> 00:56:13,420 Acesta este doar un simbol referindu-se la începutul lucru. 669 00:56:13,420 --> 00:56:17,680 Pentru ca ai declarat matrice interiorul acestei funcții, 670 00:56:17,680 --> 00:56:22,340 ceea ce compilator este de gând să faceți este să înlocuiască doar toate instanțele de variabila x 671 00:56:22,340 --> 00:56:26,400 în cazul în care sa întâmplat cu a alege să afișezi aceste 16 bytes. 672 00:56:26,400 --> 00:56:30,040 Nu se poate face asta cu char * s, deoarece s este un pointer reală. 673 00:56:30,040 --> 00:56:32,380 Este gratuit pentru a indica apoi la alte lucruri. 674 00:56:32,380 --> 00:56:36,140 x este o constantă. Tu nu poți avea punct într-o matrice diferită. >> [Elev] Ok. 675 00:56:36,140 --> 00:56:43,420 Dar această idee, această indexare, este același, indiferent de faptul dacă este o matrice tradițională 676 00:56:43,420 --> 00:56:48,230 sau în cazul în care este un pointer la ceva sau dacă este un pointer la o matrice malloced. 677 00:56:48,230 --> 00:56:59,770 Și, de fapt, este atât de echivalent că aceasta este, de asemenea, același lucru. 678 00:56:59,770 --> 00:57:05,440 Este de fapt, doar se traduce ceea ce este în interiorul a paranteze și ce a mai rămas din paranteze, 679 00:57:05,440 --> 00:57:07,970 adauga-le împreună, și dereferences. 680 00:57:07,970 --> 00:57:14,710 Deci, aceasta este la fel de valabilă ca și * (e + 3) sau s [3]. 681 00:57:16,210 --> 00:57:22,090 [Elev] Poți avea indicii care indică 2-dimensionale matrice? 682 00:57:22,090 --> 00:57:27,380 >> E mai greu. În mod tradițional, nu. 683 00:57:27,380 --> 00:57:34,720 O matrice 2-dimensional este doar o matrice 1-dimensional cu unele sintaxa convenabil 684 00:57:34,720 --> 00:57:54,110 pentru că atunci când spun int x [3] [3], aceasta este de fapt doar o matrice cu 9 valori. 685 00:57:55,500 --> 00:58:03,000 Și așa că atunci când am indicelui, compilatorul știe ce vreau să spun. 686 00:58:03,000 --> 00:58:13,090 Dacă eu spun x [1] [2], se știe că vreau să merg la al doilea rând, așa că va sări peste primele 3, 687 00:58:13,090 --> 00:58:17,460 și apoi vrea doilea lucru, în care, așa că va obține această unul. 688 00:58:17,460 --> 00:58:20,480 Dar este încă doar un singur array-dimensional. 689 00:58:20,480 --> 00:58:23,660 Și așa, dacă am vrut să atribui un pointer la care matrice, 690 00:58:23,660 --> 00:58:29,770 Aș spune int * p = x; 691 00:58:29,770 --> 00:58:33,220 Tipul de x este doar - 692 00:58:33,220 --> 00:58:38,280 E tipul dur spune lui x, deoarece ea este doar un simbol si nu este o variabilă reală, 693 00:58:38,280 --> 00:58:40,140 dar aceasta este doar o int *. 694 00:58:40,140 --> 00:58:44,840 x este doar un pointer la începutul acestui. >> [Elev] Ok. 695 00:58:44,840 --> 00:58:52,560 Și așa nu voi putea accesa [1] [2]. 696 00:58:52,560 --> 00:58:58,370 Cred că nu există sintaxă specială pentru declararea un pointer, 697 00:58:58,370 --> 00:59:12,480 ceva ridicol cum ar fi int (* p [-. ceva absolut ridicol nu știu măcar. 698 00:59:12,480 --> 00:59:17,090 Dar există o sintaxa de declarare indicii, cum ar fi, cu paranteze și lucruri. 699 00:59:17,090 --> 00:59:22,960 Acesta nu poate lăsa chiar tu faci asta. 700 00:59:22,960 --> 00:59:26,640 Aș putea privi înapoi la ceva care să-mi spui adevărul. 701 00:59:26,640 --> 00:59:34,160 Voi căuta mai târziu, în cazul în care există o sintaxă pentru punct. Dar niciodată nu va vedea. 702 00:59:34,160 --> 00:59:39,670 Și chiar și sintaxa este atât de arhaică că, dacă îl folosiți, oamenii vor fi surprinși. 703 00:59:39,670 --> 00:59:43,540 Matrice multidimensionale sunt destul de rare, așa cum este. 704 00:59:43,540 --> 00:59:44,630 Ai destul de mult - 705 00:59:44,630 --> 00:59:48,490 Ei bine, dacă faci lucruri matrice nu va fi rare, 706 00:59:48,490 --> 00:59:56,730 dar în C te rar gând să fie utilizând matrici multidimensionale. 707 00:59:57,630 --> 01:00:00,470 Da. >> [Elevului] Să presupunem că aveți o gamă foarte lung. 708 01:00:00,470 --> 01:00:03,900 >> Deci, în memoria virtuală ar părea să fie consecutive, 709 01:00:03,900 --> 01:00:05,640 cum ar fi elementele de dreptul de lângă altul, 710 01:00:05,640 --> 01:00:08,770 dar în memoria fizică, ar fi posibil ca să fi defalcată? Da >>. 711 01:00:08,770 --> 01:00:16,860 Cum functioneaza memoria virtuală este doar separă - 712 01:00:19,220 --> 01:00:24,860 Unitatea de alocare este o pagină, care tinde să fie 4 kilobytes, 713 01:00:24,860 --> 01:00:29,680 și astfel încât atunci când un proces spune, hei, vreau să folosesc această memorie, 714 01:00:29,680 --> 01:00:35,970 sistemul de operare este de gând să-l aloce 4 kilobytes pentru că blocul mic de memorie. 715 01:00:35,970 --> 01:00:39,100 Chiar dacă utilizați doar un singur octet puțin în întregul bloc de memorie, 716 01:00:39,100 --> 01:00:42,850 sistemul de operare este de gând să-i dea întregului 4 kilobytes. 717 01:00:42,850 --> 01:00:49,410 Deci, ce înseamnă acest lucru este că ar putea avea - să spunem acest lucru este stack-ul meu. 718 01:00:49,410 --> 01:00:53,180 Acest lucru ar putea fi separate stivă. Stack-ul meu ar putea fi megaocteți și megaocteți. 719 01:00:53,180 --> 01:00:55,020 Stack-ul meu ar putea fi imens. 720 01:00:55,020 --> 01:01:00,220 Dar stiva însăși trebuie să fie împărțită în pagini individuale, 721 01:01:00,220 --> 01:01:09,010 care, dacă ne uităm la peste aici să spunem că aceasta este RAM noastră, 722 01:01:09,010 --> 01:01:16,600 daca am 2 GB de RAM, aceasta este 0 adresa reală ca octet zero de RAM meu, 723 01:01:16,600 --> 01:01:22,210 și acest lucru este de 2 gigaocteți tot până aici. 724 01:01:22,210 --> 01:01:27,230 Deci aceasta pagina s-ar putea să corespundă acestei bloc de aici. 725 01:01:27,230 --> 01:01:29,400 Această pagină ar putea să corespundă acestei bloc de aici. 726 01:01:29,400 --> 01:01:31,560 Acest lucru s-ar putea să corespundă asta de aici. 727 01:01:31,560 --> 01:01:35,540 Deci, sistemul de operare este liber să atribuie memorie fizică 728 01:01:35,540 --> 01:01:39,320 la orice pagină individ arbitrar. 729 01:01:39,320 --> 01:01:46,180 Și asta înseamnă că, dacă acest lucru se întâmplă pentru a frontierei călare o matrice, 730 01:01:46,180 --> 01:01:50,070 o matrice se întâmplă să fi lăsat de acest lucru si drept de acest ordin a unei pagini, 731 01:01:50,070 --> 01:01:54,460 atunci matrice va fi împărțită în memorie fizică. 732 01:01:54,460 --> 01:01:59,280 Și apoi, când te-ai lăsat programului, atunci când procesul se termină, 733 01:01:59,280 --> 01:02:05,690 aceste mapări obține șters și apoi este liber să utilizeze aceste blocuri mici pentru alte lucruri. 734 01:02:14,730 --> 01:02:17,410 Mai multe întrebări? 735 01:02:17,410 --> 01:02:19,960 [Elev] indicatorul aritmetică. Oh, da >>. 736 01:02:19,960 --> 01:02:28,410 Siruri de caractere au fost mai usor, dar se uită la ceva de genul Ints, 737 01:02:28,410 --> 01:02:35,000 Deci, înapoi la int x [4]; 738 01:02:35,000 --> 01:02:41,810 Dacă aceasta este o matrice sau dacă este un pointer la o matrice malloced de 4 numere întregi, 739 01:02:41,810 --> 01:02:47,060 o să fie tratate în același mod. 740 01:02:50,590 --> 01:02:53,340 [Elev] Deci, matrice sunt pe heap? 741 01:03:01,400 --> 01:03:05,270 [Bowden] Matricile nu sunt pe heap. >> [Elev] Oh. 742 01:03:05,270 --> 01:03:08,320 >> [Bowden] Acest tip de matrice tinde să fie pe stiva 743 01:03:08,320 --> 01:03:12,220 dacă nu a declarat la - ignorarea variabile globale. Nu folosiți variabile globale. 744 01:03:12,220 --> 01:03:16,280 În interiorul unei funcții spun int x [4]; 745 01:03:16,280 --> 01:03:22,520 Se va crea un bloc de 4-întreg pe stivă pentru această matrice. 746 01:03:22,520 --> 01:03:26,960 Dar acest malloc (4 * sizeof (int)); este de gând să meargă pe heap. 747 01:03:26,960 --> 01:03:31,870 Dar, după acest moment pot folosi x si p destul de mult, în aceleași moduri, 748 01:03:31,870 --> 01:03:36,140 altele decât excepțiile am spus înainte despre Puteți realoca p.. 749 01:03:36,140 --> 01:03:40,960 Punct de vedere tehnic, dimensiunile lor sunt oarecum diferite, dar asta e complet irelevant. 750 01:03:40,960 --> 01:03:43,310 Niciodată nu folosi de fapt dimensiunile lor. 751 01:03:48,020 --> 01:03:56,810 P. I-ar putea spune p [3] = 2; sau x [3] = 2; 752 01:03:56,810 --> 01:03:59,680 Aveți posibilitatea să le utilizeze în exact aceleași moduri. 753 01:03:59,680 --> 01:04:01,570 Deci, aritmetică indicatorul acum - Da. 754 01:04:01,570 --> 01:04:07,390 [Elev] Nu trebuie să faci p *, dacă aveți paranteze? 755 01:04:07,390 --> 01:04:11,720 Paranteze sunt o dereference implicite. Bine >>. 756 01:04:11,720 --> 01:04:20,200 De fapt, de asemenea, ce vrei să spui cu poate te tablouri multidimensionale 757 01:04:20,200 --> 01:05:02,650 cu indicii, ceea ce se poate face este ceva de genul, să spunem, int ** pp = malloc (sizeof (int *) * 5); 758 01:05:02,650 --> 01:05:06,900 Voi scrie doar totul mai întâi. 759 01:05:37,880 --> 01:05:41,020 Nu am vrut asta. 760 01:05:41,020 --> 01:05:42,550 Bine. 761 01:05:42,550 --> 01:05:48,910 Ceea ce am făcut aici este - Asta ar trebui să fie puncte procentuale [i]. 762 01:05:48,910 --> 01:05:53,680 Deci, pp este un pointer la un pointer. 763 01:05:53,680 --> 01:06:02,420 Te mallocing puncte procentuale, pentru a indica o serie de 5 stele int. 764 01:06:02,420 --> 01:06:10,950 Deci, în memoria aveți pe pp. stivă 765 01:06:10,950 --> 01:06:20,150 O să indice o serie de 5 blocuri, care sunt toate s-au pointeri. 766 01:06:20,150 --> 01:06:28,210 Și apoi, când am malloc aici, am malloc că fiecare dintre aceste indicii individuale 767 01:06:28,210 --> 01:06:32,080 ar trebui să indice către un bloc separat de 4 octeți pe heap. 768 01:06:32,080 --> 01:06:35,870 Deci, acest puncte de la 4 octeți. 769 01:06:37,940 --> 01:06:40,660 Și aceasta puncte la un alt 4 octeți. 770 01:06:40,660 --> 01:06:43,200 >> Și toate dintre ele indica propriile 4 octeți. 771 01:06:43,200 --> 01:06:49,080 Acest lucru dă-mi o modalitate de a face lucruri multidimensionale. 772 01:06:49,080 --> 01:06:58,030 Am putea spune pp [3] [4], dar acum acest lucru nu este același lucru ca tablouri multidimensionale 773 01:06:58,030 --> 01:07:05,390 deoarece tablouri multidimensionale a tradus [3] [4] într-un singur diferența în matrice x. 774 01:07:05,390 --> 01:07:14,790 Acest p. dereferences, accesează indicele treia, atunci dereferences că 775 01:07:14,790 --> 01:07:20,790 și de acces - 4 ar fi invalidă - indicele de secunde. 776 01:07:24,770 --> 01:07:31,430 Întrucât, atunci când am avut int x [3] [4] înainte de a ca o matrice multidimensional 777 01:07:31,430 --> 01:07:35,740 și atunci când faceți dublu suport este într-adevăr doar un singur dereference, 778 01:07:35,740 --> 01:07:40,490 te în urma unui pointer unic și apoi un offset, 779 01:07:40,490 --> 01:07:42,850 aceasta este într-adevăr referințele 2D. 780 01:07:42,850 --> 01:07:45,840 Urmați 2 pointeri separate. 781 01:07:45,840 --> 01:07:50,420 Deci, acest punct de vedere tehnic, de asemenea, vă permite să aveți tablouri multidimensionale 782 01:07:50,420 --> 01:07:53,550 în cazul în care fiecare individ este matrice de diferite dimensiuni. 783 01:07:53,550 --> 01:07:58,000 Deci, eu cred că tablouri multidimensionale zimțate este ceea ce se numește 784 01:07:58,000 --> 01:08:01,870 într-adevăr, deoarece primul lucru pe care ar putea să indice ceva care are 10 de elemente, 785 01:08:01,870 --> 01:08:05,540 al doilea lucru ar putea indica ceva care are 100 de elemente. 786 01:08:05,540 --> 01:08:10,790 [Elev] Exista vreo limita la numarul de indicii puteți avea 787 01:08:10,790 --> 01:08:14,290 arătând spre alte indicii? Nu >> 788 01:08:14,290 --> 01:08:17,010 Puteți avea int ***** p.. 789 01:08:18,050 --> 01:08:23,760 Înapoi la aritmetică indicatorul - >> [elev] Oh. Da >>. 790 01:08:23,760 --> 01:08:35,649 [Elev] Dacă am int *** p și apoi să fac o dereferencing și spun * p este egal cu această valoare, 791 01:08:35,649 --> 01:08:39,560 este doar de gând să facă un nivel de dereferencing? Da >>. 792 01:08:39,560 --> 01:08:43,340 Deci, dacă vreau să acceseze lucru care indicatorul este îndreptat la ultima - 793 01:08:43,340 --> 01:08:46,210 Apoi te faci p ***. Bine >>. 794 01:08:46,210 --> 01:08:54,080 Deci, aceasta este de puncte p la 1 bloc, punctele de la un alt bloc, punctele de la un alt bloc. 795 01:08:54,080 --> 01:09:02,010 Apoi, dacă faci * p = altceva, atunci se schimbă această 796 01:09:02,010 --> 01:09:13,640 pentru a indica acum la un bloc diferit. Bine >>. 797 01:09:13,640 --> 01:09:17,649 >> [Bowden] Iar dacă acestea au fost malloced, apoi s-au scurs de memorie acum 798 01:09:17,649 --> 01:09:20,430 excepția cazului în care se întâmplă să aibă referințe diferite ale acestor 799 01:09:20,430 --> 01:09:25,270 din moment ce nu se poate obține înapoi la acelea pe care tocmai l-ați aruncat. 800 01:09:25,270 --> 01:09:29,550 Pointer aritmetică. 801 01:09:29,550 --> 01:09:36,310 int x [4]; este de gând să aloce o serie de 4 numere întregi 802 01:09:36,310 --> 01:09:40,670 unde x este de gând să indice începutul matrice. 803 01:09:40,670 --> 01:09:50,420 Asa ca atunci cand spun ceva de genul x [1], vreau să însemne merge la întreg doua matrice, 804 01:09:50,420 --> 01:09:53,319 care ar fi acesta. 805 01:09:53,319 --> 01:10:04,190 Dar de fapt, asta e 4 octeți în matrice, deoarece acest număr întreg durează până la 4 octeți. 806 01:10:04,190 --> 01:10:08,470 Deci, un offset de 1 înseamnă cu adevărat un offset de 1 807 01:10:08,470 --> 01:10:12,030 ori dimensiunea indiferent de tipul de matrice este. 808 01:10:12,030 --> 01:10:17,170 Acesta este un tablou de întregi, așa că știe să facă de 1 ori marimea int atunci când vrea să le compenseze. 809 01:10:17,170 --> 01:10:25,260 Alte sintaxa. Amintiți-vă că acest lucru este echivalent cu * (x + 1); 810 01:10:25,260 --> 01:10:35,250 Când spun indicatorul + 1, ceea ce este care returnează adresa care indicatorul este stocarea 811 01:10:35,250 --> 01:10:40,360 plus 1 de ori dimensiunea de tipul de pointer. 812 01:10:40,360 --> 01:10:59,510 Deci, daca x = ox100, atunci x + 1 = ox104. 813 01:10:59,510 --> 01:11:19,750 Și vă puteți abuza de acest lucru și spune ceva de genul char * c = (char *) x; 814 01:11:19,750 --> 01:11:23,050 iar acum c este de gând să fie aceeași adresă ca și x. 815 01:11:23,050 --> 01:11:26,040 C va fi egală cu ox100, 816 01:11:26,040 --> 01:11:31,490 dar C + 1 va fi egal cu ox101 817 01:11:31,490 --> 01:11:38,030 deoarece aritmetică indicatorul depinde de tipul de indicatorul pe care îl adăugați la. 818 01:11:38,030 --> 01:11:45,390 Deci, C + 1, se pare c la, este un pointer char, asa ca va adăuga 1 ori dimensiunea char, 819 01:11:45,390 --> 01:11:48,110 care este întotdeauna o să fie de 1, astfel încât să obțineți 101, 820 01:11:48,110 --> 01:11:54,890 întrucât, dacă fac x, care este, de asemenea, încă 100, x + 1 va fi 104. 821 01:11:56,660 --> 01:12:06,340 [Elev] Poți folosi C + +, în scopul de a avansa indicatorul de 1? 822 01:12:06,340 --> 01:12:09,810 Da, poți. 823 01:12:09,810 --> 01:12:16,180 Nu puteți face asta cu x, deoarece x este doar un simbol, este o constantă, nu se poate schimba x. 824 01:12:16,180 --> 01:12:22,610 >> Dar C se întâmplă să fie doar un pointer, deci c + + este perfect valabilă și se va incrementa cu 1. 825 01:12:22,610 --> 01:12:32,440 Dacă c au fost doar o int *, apoi C + + ar fi 104. 826 01:12:32,440 --> 01:12:41,250 + + Are aritmetică indicatorul la fel ca C + 1 ar fi făcut aritmetică indicatorul. 827 01:12:43,000 --> 01:12:48,870 Acesta este de fapt modul în care o mulțime de lucruri, cum ar fi un fel de îmbinare - 828 01:12:49,670 --> 01:12:55,710 În loc de a crea copii de lucruri, puteți trece în schimb - 829 01:12:55,710 --> 01:13:02,400 Ca și în cazul în care am vrut să treacă această jumătate din matrice - hai să șteargă o parte din aceasta. 830 01:13:04,770 --> 01:13:10,520 Să spunem că am vrut să treacă această parte a matrice într-o funcție. 831 01:13:10,520 --> 01:13:12,700 Ce mi-ar trece la această funcție? 832 01:13:12,700 --> 01:13:17,050 Dacă eu trec x, am trecut de această adresă. 833 01:13:17,050 --> 01:13:23,780 Dar eu vreau să treci această adresă special. Deci, ce ar trebui să treacă? 834 01:13:23,780 --> 01:13:26,590 [Elev] Pointer + 2? 835 01:13:26,590 --> 01:13:29,350 [Bowden] Deci x + 2. Da. 836 01:13:29,350 --> 01:13:31,620 Asta va fi această adresă. 837 01:13:31,620 --> 01:13:42,810 Veți de asemenea, foarte frecvent, o văd ca pe x [2] și apoi adresa asta. 838 01:13:42,810 --> 01:13:47,850 Deci, aveți nevoie pentru a lua adresa de ea, deoarece suportul este o dereference implicită. 839 01:13:47,850 --> 01:13:53,250 x [2] se referă la valoarea care este în această casetă, și apoi doriți adresa acea cutie, 840 01:13:53,250 --> 01:13:56,850 asa ai spus si x [2]. 841 01:13:56,850 --> 01:14:02,880 Deci asta e modul în care ceva intr-un fel de îmbinare în cazul în care doriți să treci jumătate din lista de la ceva 842 01:14:02,880 --> 01:14:08,790 într-adevăr doar treci & x [2], iar acum în ceea ce privește apelul recursiv este în cauză, 843 01:14:08,790 --> 01:14:12,510 matrice noul meu începe acolo. 844 01:14:12,510 --> 01:14:15,130 Întrebări last minute. 845 01:14:15,130 --> 01:14:20,050 [Elev] Dacă nu vom pune un ampersand sau - ceea ce e numit? Steaua >>? 846 01:14:20,050 --> 01:14:23,200 [Elev] stele. >> Punct de vedere tehnic, operatorul dereference, dar - >> [elev] dereference. 847 01:14:23,200 --> 01:14:29,310 >> Dacă nu vom pune o stea sau un ampersand, ce se întâmplă dacă eu spun doar y = x si x este un pointer? 848 01:14:29,310 --> 01:14:34,620 Care este tipul de y? >> [Elev] Voi spune doar că e indicatorul 2. 849 01:14:34,620 --> 01:14:38,270 Deci, dacă spunem că y = x, x acum și punctul y la același lucru. >> [Elev] Punctul pentru același lucru. 850 01:14:38,270 --> 01:14:45,180 Și dacă x este un pointer int? Aceasta ar plânge >> pentru că nu se poate atribui pointeri. 851 01:14:45,180 --> 01:14:46,540 [Elev] Ok. 852 01:14:46,540 --> 01:14:51,860 Amintiți-vă că indicii, chiar dacă le-am trage cu săgeți, 853 01:14:51,860 --> 01:15:02,010 într-adevăr toate acestea magazin - int * x - x este într-adevăr toate stocarea e ceva de genul ox100, 854 01:15:02,010 --> 01:15:06,490 care se întâmplă să reprezinte ca semn de blocul stocate la 100. 855 01:15:06,490 --> 01:15:19,660 Deci, atunci când spun int * y = x; Eu doar copierea ox100 în Y, 856 01:15:19,660 --> 01:15:24,630 pe care suntem doar de gând să reprezinte ca y, de asemenea, arătând spre ox100. 857 01:15:24,630 --> 01:15:39,810 Și dacă eu spun int i = (int) x; apoi i se va stoca orice valoare a ox100 este 858 01:15:39,810 --> 01:15:45,100 în interiorul acestuia, dar acum va fi interpretată ca un întreg în loc de un pointer. 859 01:15:45,100 --> 01:15:49,310 Dar ai nevoie de turnat sau altceva se va plânge. 860 01:15:49,310 --> 01:15:53,300 [Elev] Deci vrei să spui să arunce - 861 01:15:53,300 --> 01:16:00,290 Este de gând să fie turnare int de int x sau y turnare a? 862 01:16:00,290 --> 01:16:03,700 [Bowden] Ce? 863 01:16:03,700 --> 01:16:07,690 [Elev] Ok. După aceste paranteze este acolo va fi un x sau ay acolo? 864 01:16:07,690 --> 01:16:11,500 >> [Bowden] Fie. x și y sunt echivalente. >> [Elev] Ok. 865 01:16:11,500 --> 01:16:14,390 Pentru că sunt atât pointeri. Da >>. 866 01:16:14,390 --> 01:16:21,050 [Elev] Deci, s-ar păstra hexazecimal 100 în formă întreg? >> [Bowden] Da. 867 01:16:21,050 --> 01:16:23,620 Dar nu valoarea a ceea ce se arată la. 868 01:16:23,620 --> 01:16:29,940 [Bowden] Da. >> [Elev] Deci, doar adresa în formă întreg. Bine. 869 01:16:29,940 --> 01:16:34,720 [Bowden] Dacă vrei să bizar pentru un motiv oarecare, 870 01:16:34,720 --> 01:16:38,900 ai putea face exclusiv cu pointeri și niciodată a face cu numere întregi 871 01:16:38,900 --> 01:16:49,240 și să fie la fel ca int * x = 0. 872 01:16:49,240 --> 01:16:53,000 Atunci ai de gând să obțineți cu adevărat confuz dată aritmetică indicatorul incepe sa se intample. 873 01:16:53,000 --> 01:16:56,570 Deci numerele pe care le stochează sunt lipsite de sens. 874 01:16:56,570 --> 01:16:58,940 E doar modul în care ajunge să le interpreteze. 875 01:16:58,940 --> 01:17:02,920 Deci, eu sunt liber să copiați ox100 de la un * int la un int, 876 01:17:02,920 --> 01:17:07,790 si eu sunt liber să atribuie - Esti, probabil, va fi țipat la turnare pentru a nu - 877 01:17:07,790 --> 01:17:18,160 Sunt liber pentru a atribui ceva de genul (int *) * ox1234 în acest int arbitrară. 878 01:17:18,160 --> 01:17:25,480 Deci, ox123 este la fel de valabil o adresă de memorie așa cum este și y. 879 01:17:25,480 --> 01:17:32,060 & Y se întâmplă să se întoarcă ceva care este destul de mult ox123. 880 01:17:32,060 --> 01:17:35,430 [Elev] Ar fi ca un mod foarte misto de a merge la hexazecimal pentru a forma zecimală, 881 01:17:35,430 --> 01:17:39,230 ca în cazul în care aveți un pointer și l-ați aruncat ca un int? 882 01:17:39,230 --> 01:17:44,860 [Bowden] Puteți imprima folosind de fapt doar ca printf. 883 01:17:44,860 --> 01:17:50,300 Să spunem că am int y = 100. 884 01:17:50,300 --> 01:18:02,700 Deci printf (% d \ n - așa cum ar trebui să știi deja - că tipărarea ca un întreg, x%. 885 01:18:02,700 --> 01:18:05,190 Vom imprima doar ca hexazecimal. 886 01:18:05,190 --> 01:18:10,760 Deci, un pointer nu este stocată ca hexazecimal, 887 01:18:10,760 --> 01:18:12,960 și un întreg nu este stocat ca zecimal. 888 01:18:12,960 --> 01:18:14,700 Totul este stocat ca un binar. 889 01:18:14,700 --> 01:18:17,950 E doar că avem tendința de a vedea indicii ca hexazecimal 890 01:18:17,950 --> 01:18:23,260 pentru că ne gândim la lucruri din aceste blocuri 4-byte, 891 01:18:23,260 --> 01:18:25,390 și adresele de memorie tind să fie familiarizați. 892 01:18:25,390 --> 01:18:28,890 Suntem ca, în cazul în care începe cu BF, apoi se întâmplă să fie pe stiva. 893 01:18:28,890 --> 01:18:35,560 Deci e doar interpretarea noastră de pointeri ca hexazecimal. 894 01:18:35,560 --> 01:18:39,200 Bine. Alte întrebări ultimele? 895 01:18:39,200 --> 01:18:41,700 >> Voi fi aici pentru un pic după ce, dacă aveți altceva. 896 01:18:41,700 --> 01:18:46,070 Și asta e sfârșitul acelui. 897 01:18:46,070 --> 01:18:48,360 >> [Elev] Yay! [Aplauze] 898 01:18:51,440 --> 01:18:53,000 >> [CS50.TV]