1 00:00:00,000 --> 00:00:02,520 [Powered by Google Translate] [Avsnitt 4 - Mer Bekväm] 2 00:00:02,520 --> 00:00:04,850 [Rob Bowden - Harvarduniversitetet] 3 00:00:04,850 --> 00:00:07,370 [Detta är CS50. - CS50.TV] 4 00:00:08,920 --> 00:00:13,350 Vi har en frågesport i morgon, om ni inte visste det. 5 00:00:14,810 --> 00:00:20,970 Det är i princip på allt du kan ha sett i klassen eller borde ha sett i klassen. 6 00:00:20,970 --> 00:00:26,360 Det inkluderar pekare, även om de är en mycket ny tråd. 7 00:00:26,360 --> 00:00:29,860 Du bör åtminstone förstå den höga dem. 8 00:00:29,860 --> 00:00:34,760 Allt som var borta över i klassen bör du förstå att testet. 9 00:00:34,760 --> 00:00:37,320 Så om du har frågor om dem, kan du be dem nu. 10 00:00:37,320 --> 00:00:43,280 Men detta kommer att bli en mycket elev-ledda session där ni ställer frågor, 11 00:00:43,280 --> 00:00:45,060 så förhoppningsvis folk har frågor. 12 00:00:45,060 --> 00:00:48,020 Har någon frågor? 13 00:00:49,770 --> 00:00:52,090 Ja. >> [Elev] Kan du gå över pekare igen? 14 00:00:52,090 --> 00:00:54,350 Jag ska gå över pekare. 15 00:00:54,350 --> 00:00:59,180 Alla dina variabler lever nödvändigtvis i minnet, 16 00:00:59,180 --> 00:01:04,450 men brukar du oroa dig inte om det och du bara säga x + 2 och y + 3 17 00:01:04,450 --> 00:01:07,080 och kompilatorn kommer att räkna ut var de saker lever för dig. 18 00:01:07,080 --> 00:01:12,990 När du arbetar med pekare, nu är du uttryckligen använder dessa minnesadresser. 19 00:01:12,990 --> 00:01:19,800 Så en enda variabel kommer alltid bara bor på en enda adress vid varje given tidpunkt. 20 00:01:19,800 --> 00:01:24,040 Om vi ​​vill förklara en pekare, vad den typ kommer att se ut? 21 00:01:24,040 --> 00:01:26,210 >> Jag vill förklara en pekare sid. Hur ser den typ ut? 22 00:01:26,210 --> 00:01:33,530 [Eleven] int * p. >> Ja. Så int * p. 23 00:01:33,530 --> 00:01:38,030 Och hur gör jag det pekar på x? >> [Elev] Ampersand. 24 00:01:40,540 --> 00:01:45,300 [Bowden] Så ampersand är bokstavligen kallas adressen operatören. 25 00:01:45,300 --> 00:01:50,460 Så när jag säger och X det blir minnesadressen för variabeln x. 26 00:01:50,460 --> 00:01:56,790 Så nu har jag pekaren p, och var som helst i min kod jag kan använda * p 27 00:01:56,790 --> 00:02:02,960 eller jag kunde använda x och det kommer att bli exakt samma sak. 28 00:02:02,960 --> 00:02:09,520 (* P). Vad är detta gör? Vad betyder det stjärna? 29 00:02:09,520 --> 00:02:13,120 [Elev] Det betyder ett värde på den punkten. >> Ja. 30 00:02:13,120 --> 00:02:17,590 Så om vi ser på det, kan det vara mycket värdefullt att dra ut diagrammen 31 00:02:17,590 --> 00:02:22,230 där detta är en liten låda med minne för x, som råkar ha värdet 4, 32 00:02:22,230 --> 00:02:25,980 då har vi en liten låda med minne för p, 33 00:02:25,980 --> 00:02:31,590 och så p pekar på x, så vi drar en pil från p till x. 34 00:02:31,590 --> 00:02:40,270 Så när vi säger * p vi säger gå till rutan som är p. 35 00:02:40,270 --> 00:02:46,480 Star är att följa pilen och sedan göra vad du vill med den rutan där. 36 00:02:46,480 --> 00:03:01,090 Så jag kan säga * p = 7, och som kommer att gå till den ruta som är x och förändring som till 7. 37 00:03:01,090 --> 00:03:13,540 Eller jag kunde säga int z = * P * 2, det är förvirrande eftersom det är stjärna, stjärna. 38 00:03:13,540 --> 00:03:19,230 Det en stjärna är dereferencing p, den andra stjärnan multiplicera med 2. 39 00:03:19,230 --> 00:03:26,780 Märker jag kunde ha lika bra ersatt * p med x. 40 00:03:26,780 --> 00:03:29,430 Du kan använda dem på samma sätt. 41 00:03:29,430 --> 00:03:38,000 Och sedan senare jag kan få p pekar på en helt ny grej. 42 00:03:38,000 --> 00:03:42,190 Jag kan bara säga p = &z; 43 00:03:42,190 --> 00:03:44,940 Så nu p inte längre pekar på X, den pekar på z.. 44 00:03:44,940 --> 00:03:50,510 Och varje gång jag gör * p är det samma som att göra z.. 45 00:03:50,510 --> 00:03:56,170 Så bra med detta är när vi börjar komma in funktioner. 46 00:03:56,170 --> 00:03:59,790 >> Det är typ av meningslöst att förklara en pekare som pekar på något 47 00:03:59,790 --> 00:04:03,140 och då du bara dereferencing det 48 00:04:03,140 --> 00:04:06,060 när du kunde ha använt den ursprungliga variabeln till att börja med. 49 00:04:06,060 --> 00:04:18,190 Men när du kommer in funktioner - så låt oss säga att vi har någon funktion, int foo, 50 00:04:18,190 --> 00:04:32,810 som tar en pekare och bara gör * p = 6; 51 00:04:32,810 --> 00:04:39,990 Som vi såg tidigare med swap, kan du inte göra en effektiv swap och en separat funktion 52 00:04:39,990 --> 00:04:45,180 genom att bara passera heltal eftersom allt i C alltid förbi värde. 53 00:04:45,180 --> 00:04:48,360 Även när du passerar tips du passerar värde. 54 00:04:48,360 --> 00:04:51,940 Det råkar vara så att dessa värden är minnesadresser. 55 00:04:51,940 --> 00:05:00,770 Så när jag säger foo (p), jag passerar pekaren till funktionen foo 56 00:05:00,770 --> 00:05:03,910 och sedan foo gör * p = 6; 57 00:05:03,910 --> 00:05:08,600 Så inne i den funktionen, är * p fortfarande lika med x, 58 00:05:08,600 --> 00:05:12,720 men jag kan inte använda X insidan av denna funktion eftersom det inte scoped inom denna funktion. 59 00:05:12,720 --> 00:05:19,510 Så * p = 6 är det enda sättet jag kan komma åt en lokal variabel från en annan funktion. 60 00:05:19,510 --> 00:05:23,600 Eller, ja, pekare är det enda sättet jag kan komma åt en lokal variabel från en annan funktion. 61 00:05:23,600 --> 00:05:31,600 [Elev] Låt oss säga att du vill returnera en pekare. Hur exakt gör du det? 62 00:05:31,600 --> 00:05:44,270 [Bowden] Returnera en pekare som i något som int y = 3, retur & Y? >> [Elev] Ja. 63 00:05:44,270 --> 00:05:48,480 [Bowden] Okej. Du ska aldrig göra detta. Det är illa. 64 00:05:48,480 --> 00:05:59,480 Jag tror jag såg i dessa föreläsningsbilder du började se hela denna bild av minne 65 00:05:59,480 --> 00:06:02,880 där upp här har du minnesadress 0 66 00:06:02,880 --> 00:06:09,550 och här nere har du minnesadress 4 spelningar eller 2 till 32. 67 00:06:09,550 --> 00:06:15,120 Så du har lite grejer och vissa saker och då har du din stack 68 00:06:15,120 --> 00:06:21,780 och du har din hög, som du precis börjat lära sig om, att växa upp. 69 00:06:21,780 --> 00:06:24,390 [Elev] Är inte högen ovanför stapeln? 70 00:06:24,390 --> 00:06:27,760 >> Ja. Högen är på topp, är det inte? >> [Elev] Tja, satte han 0 ovanpå. 71 00:06:27,760 --> 00:06:30,320 [Elev] Åh, satte han 0 ovanpå. >> [Elev] Åh, okej. 72 00:06:30,320 --> 00:06:36,060 Friskrivningsklausul: Överallt med CS50 du kommer att se det här sättet. >> [Elev] Okej. 73 00:06:36,060 --> 00:06:40,290 Det är bara det att när du första ser stackar, 74 00:06:40,290 --> 00:06:45,000 som när du tänker på en bunt du tänker att stapla saker ovanpå varandra. 75 00:06:45,000 --> 00:06:50,810 Så vi tenderar att vända detta runt så stapeln växer upp som en bunt normalt skulle 76 00:06:50,810 --> 00:06:55,940 istället för stapeln hänger ned. >> [Elev] inte högar tekniskt växa upp också, men? 77 00:06:55,940 --> 00:07:01,100 Det beror på vad du menar med att växa upp. 78 00:07:01,100 --> 00:07:04,010 Stapeln och heap växa alltid i motsatta riktningar. 79 00:07:04,010 --> 00:07:09,420 En stack alltid växer upp i den meningen att den växer upp 80 00:07:09,420 --> 00:07:12,940 mot högre minnesadresser, och heap växer ned 81 00:07:12,940 --> 00:07:17,260 att det växer mot lägre minnesadresser. 82 00:07:17,260 --> 00:07:20,250 Så toppen är 0 och botten är hög minnesadresser. 83 00:07:20,250 --> 00:07:26,390 De är båda växande, bara i motsatta riktningar. 84 00:07:26,390 --> 00:07:29,230 [Elev] Jag menade bara att eftersom du sa att du sätter stacken på botten 85 00:07:29,230 --> 00:07:33,640 eftersom det verkar mer intuitivt eftersom för stapeln att börja på toppen av en hög, 86 00:07:33,640 --> 00:07:37,520 hög är på toppen av sig själv också, så that - >> Ja. 87 00:07:37,520 --> 00:07:44,960 Du tror också av högen som växer upp och större, men stacken mer. 88 00:07:44,960 --> 00:07:50,280 Så stack är det som vi slags vill visa växa upp. 89 00:07:50,280 --> 00:07:55,390 Men överallt man ser något annat kommer att visa adress 0 upptill 90 00:07:55,390 --> 00:07:59,590 och den högsta minnesadress i botten, så det här är din vanliga syn på minnet. 91 00:07:59,590 --> 00:08:02,100 >> Har du en fråga? 92 00:08:02,100 --> 00:08:04,270 [Elev] Kan du berätta mer om högen? 93 00:08:04,270 --> 00:08:06,180 Ja. Jag kommer till det på en sekund. 94 00:08:06,180 --> 00:08:12,220 Först gå tillbaka till varför återvänder och y är en dålig sak, 95 00:08:12,220 --> 00:08:18,470 på stacken har du ett gäng stack ramar som representerar alla funktioner 96 00:08:18,470 --> 00:08:20,460 som har kallats. 97 00:08:20,460 --> 00:08:27,990 Så ignorera tidigare saker är toppen av din stack kommer alltid att vara den viktigaste funktionen 98 00:08:27,990 --> 00:08:33,090 eftersom det är den första funktionen som är som anropas. 99 00:08:33,090 --> 00:08:37,130 Och sedan när du ringer en annan funktion, stapeln kommer att växa ner. 100 00:08:37,130 --> 00:08:41,640 Så om jag kallar någon funktion, foo, och det blir en egen stack ram, 101 00:08:41,640 --> 00:08:47,280 Det kan ringa någon funktion, bar, det blir en egen stack ram. 102 00:08:47,280 --> 00:08:49,840 Och bar kan vara rekursiv och det kan kalla sig, 103 00:08:49,840 --> 00:08:54,150 och så att det andra samtalet till bar kommer att få sin egen stack ram. 104 00:08:54,150 --> 00:08:58,880 Och så vad som händer i dessa stack ramar är alla lokala variabler 105 00:08:58,880 --> 00:09:03,450 och alla funktionsargument som - 106 00:09:03,450 --> 00:09:08,730 Alla saker som är lokalt scoped till denna funktion gå i dessa stack ramar. 107 00:09:08,730 --> 00:09:21,520 Så det betyder när jag sa något i stil bar är en funktion, 108 00:09:21,520 --> 00:09:29,270 Jag ska bara förklara ett heltal och sedan returnera en pekare till den heltal. 109 00:09:29,270 --> 00:09:33,790 Så var bor y? 110 00:09:33,790 --> 00:09:36,900 [Eleven] y bor i baren. >> [Bowden] Ja. 111 00:09:36,900 --> 00:09:45,010 Någonstans i denna lilla torget i minnet är en littler torg som har Y i den. 112 00:09:45,010 --> 00:09:53,370 När jag återvänder & Y, jag returnerar en pekare till denna lilla block av minne. 113 00:09:53,370 --> 00:09:58,400 Men sedan när en funktion återvänder, får sin stack ram dök upp i stacken. 114 00:10:01,050 --> 00:10:03,530 Och det är därför det kallas stack. 115 00:10:03,530 --> 00:10:06,570 Det är som stapeln datastruktur, om du vet vad det är. 116 00:10:06,570 --> 00:10:11,580 Eller ens som en stapel av brickor är alltid exempel, 117 00:10:11,580 --> 00:10:16,060 viktigaste kommer att gå på botten, då den första funktionen du anropar kommer att gå på toppen av det, 118 00:10:16,060 --> 00:10:20,400 och du kan inte gå tillbaka till huvud tills du kommer tillbaka från alla funktioner som har kallats 119 00:10:20,400 --> 00:10:22,340 som har placerats ovanpå den. 120 00:10:22,340 --> 00:10:28,650 >> [Elev] Så om du gjorde tillbaka & Y, detta värde kan ändras utan föregående meddelande. 121 00:10:28,650 --> 00:10:31,290 Ja, it's - >> [elev] Det kan vara över. >> Ja. 122 00:10:31,290 --> 00:10:34,660 Det är helt - Om du försöker och - 123 00:10:34,660 --> 00:10:38,040 Detta skulle också vara en int * bar eftersom det tillbaka en pekare, 124 00:10:38,040 --> 00:10:41,310 så att dess returtyp är int *. 125 00:10:41,310 --> 00:10:46,500 Om du försöker använda returvärdet av denna funktion är det odefinierat beteende 126 00:10:46,500 --> 00:10:51,770 eftersom det pekare pekar dåligt minne. >> [Elev] Okej. 127 00:10:51,770 --> 00:11:01,250 Så vad händer om till exempel, förklarade man int * y = malloc (sizeof (int))? 128 00:11:01,250 --> 00:11:03,740 Det är bättre. Ja. 129 00:11:03,740 --> 00:11:07,730 [Elev] Vi talade om hur när vi drar saker till vår papperskorgen 130 00:11:07,730 --> 00:11:11,750 de är faktiskt inte raderas, vi bara förlora sina pekare. 131 00:11:11,750 --> 00:11:15,550 Så i det här fallet inte radera vi faktiskt värde eller är det fortfarande kvar i minnet? 132 00:11:15,550 --> 00:11:19,130 För det mesta, det kommer att finnas kvar. 133 00:11:19,130 --> 00:11:24,220 Men låt oss säga att vi råkar kalla någon annan funktion, baz. 134 00:11:24,220 --> 00:11:28,990 Baz kommer att få sin egen stack ram på här. 135 00:11:28,990 --> 00:11:31,470 Det kommer att skriva över allt det här, 136 00:11:31,470 --> 00:11:34,180 och sedan om du försöker senare och använda pekare som du fick tidigare, 137 00:11:34,180 --> 00:11:35,570 det kommer inte att vara samma värde. 138 00:11:35,570 --> 00:11:38,150 Det kommer att ha förändrats bara för att du heter funktionen Baz. 139 00:11:38,150 --> 00:11:43,080 [Elev] Men hade vi inte, skulle vi fortfarande få 3? 140 00:11:43,080 --> 00:11:44,990 [Bowden] Med all sannolikhet skulle du. 141 00:11:44,990 --> 00:11:49,670 Men du kan inte lita på det. C säger bara odefinierat beteende. 142 00:11:49,670 --> 00:11:51,920 >> [Elev] Åh, det gör det. Okej. 143 00:11:51,920 --> 00:11:58,190 Så när du vill returnera en pekare, det är där malloc kommer i användning. 144 00:12:00,930 --> 00:12:15,960 Jag skriver faktiskt bara tillbaka malloc (3 * sizeof (int)). 145 00:12:17,360 --> 00:12:24,050 Vi går över malloc mer i en sekund, men tanken på malloc är alla dina lokala variabler 146 00:12:24,050 --> 00:12:26,760 alltid gå på stacken. 147 00:12:26,760 --> 00:12:31,570 Allt som är malloced går på högen, och det kommer alltid och alltid vara på högen 148 00:12:31,570 --> 00:12:34,490 tills du frigöra uttryckligen det. 149 00:12:34,490 --> 00:12:42,130 Så detta betyder att när du malloc något, det kommer att överleva efter funktionen returnerar. 150 00:12:42,130 --> 00:12:46,800 [Elev] Kommer det att överleva efter det att programmet stannar? >> Nej 151 00:12:46,800 --> 00:12:53,180 Okej, så det kommer att vara där tills programmet är helt klar att köra. >> Ja. 152 00:12:53,180 --> 00:12:57,510 Vi kan gå över uppgifter om vad som händer när programmet stannar. 153 00:12:57,510 --> 00:13:02,150 Du kan behöva påminna mig, men det är ett separat sak helt. 154 00:13:02,150 --> 00:13:04,190 [Elev] Så malloc skapar en pekare? >> Ja. 155 00:13:04,190 --> 00:13:13,030 Malloc - >> [elev] Jag tror malloc betecknar ett block av minne som en pekare kan använda. 156 00:13:15,400 --> 00:13:19,610 [Bowden] Jag vill ha diagrammet igen. >> [Elev] Så denna funktion fungerar, men? 157 00:13:19,610 --> 00:13:26,430 [Eleven] Ja, malloc betecknar ett block av minne som du kan använda, 158 00:13:26,430 --> 00:13:30,470 och sedan returnerar adressen för det första blocket i detta minne. 159 00:13:30,470 --> 00:13:36,750 >> [Bowden] Ja. Så när du malloc, du gripa tag i vissa block av minne 160 00:13:36,750 --> 00:13:38,260 Det är för närvarande i högen. 161 00:13:38,260 --> 00:13:43,040 Om stacken är alltför liten, då högen är bara kommer att växa, och det växer i denna riktning. 162 00:13:43,040 --> 00:13:44,650 Så låt oss säga högen är för liten. 163 00:13:44,650 --> 00:13:49,960 Då är det på väg att växa lite och returnera en pekare till detta block som bara växte. 164 00:13:49,960 --> 00:13:55,130 När du gratis grejer, du gör mer utrymme i högen, 165 00:13:55,130 --> 00:14:00,030 så då en senare ringa till malloc kan återanvända det minne som du tidigare hade befriat. 166 00:14:00,030 --> 00:14:09,950 Det viktiga malloc och gratis är att det ger dig fullständig kontroll 167 00:14:09,950 --> 00:14:12,700 under hela livstiden för dessa minnesblock. 168 00:14:12,700 --> 00:14:15,420 Globala variabler är alltid levande. 169 00:14:15,420 --> 00:14:18,500 Lokala variabler är levande inom deras tillämpningsområde. 170 00:14:18,500 --> 00:14:22,140 Så snart du går förbi en klammerparentes, de lokala variablerna är döda. 171 00:14:22,140 --> 00:14:28,890 Malloced minne lever när du vill att det ska vara vid liv 172 00:14:28,890 --> 00:14:33,480 och sedan frigörs när du säger det att släppas. 173 00:14:33,480 --> 00:14:38,420 De är faktiskt de enda 3 typer av minne, verkligen. 174 00:14:38,420 --> 00:14:41,840 Det finns automatisk minneshantering, vilket är stacken. 175 00:14:41,840 --> 00:14:43,840 Saker händer åt dig automatiskt. 176 00:14:43,840 --> 00:14:46,910 När du säger int x, minne allokeras för int x. 177 00:14:46,910 --> 00:14:51,630 När X går utanför ramen, är minnet återvinns för x. 178 00:14:51,630 --> 00:14:54,790 Sedan finns dynamiskt minneshantering, vilket är vad malloc är, 179 00:14:54,790 --> 00:14:56,740 vilket är när du har kontroll. 180 00:14:56,740 --> 00:15:01,290 Du bestämmer dynamiskt när minnet bör och inte bör fördelas. 181 00:15:01,290 --> 00:15:05,050 Och sedan finns det statiska, vilket innebär bara att det lever för evigt, 182 00:15:05,050 --> 00:15:06,610 vilket är vad globala variabler är. 183 00:15:06,610 --> 00:15:10,240 De är bara alltid i minnet. 184 00:15:10,960 --> 00:15:12,760 >> Frågor? 185 00:15:14,490 --> 00:15:17,230 [Elev] Kan du definiera ett block bara genom att använda klammerparenteser 186 00:15:17,230 --> 00:15:21,220 men inte behöva ha en if-sats eller en while eller nåt sånt? 187 00:15:21,220 --> 00:15:29,130 Du kan definiera ett block som i en funktion, men det har klammerparenteser också. 188 00:15:29,130 --> 00:15:32,100 [Elev] Så du kan inte bara ha som en slumpmässig par klammerparenteserna i koden 189 00:15:32,100 --> 00:15:35,680 som har lokala variabler? >> Ja, det kan du. 190 00:15:35,680 --> 00:15:45,900 Inuti int bar vi kunde ha {int y = 3;}. 191 00:15:45,900 --> 00:15:48,440 Det är tänkt att vara här. 192 00:15:48,440 --> 00:15:52,450 Men som definierar fullständigt omfattningen av int y. 193 00:15:52,450 --> 00:15:57,320 Efter den andra klammerparentes kan y inte användas längre. 194 00:15:57,910 --> 00:16:00,630 Man nästan aldrig göra det, dock. 195 00:16:02,940 --> 00:16:07,370 Komma tillbaka till vad som händer när ett program avslutas, 196 00:16:07,370 --> 00:16:18,760 Det är lite av en missuppfattning / halv lögn som vi ger för att bara göra saker och ting lättare. 197 00:16:18,760 --> 00:16:24,410 Vi berättar att när du allokera minne 198 00:16:24,410 --> 00:16:29,860 du fördela lite bit av RAM-minne för den variabeln. 199 00:16:29,860 --> 00:16:34,190 Men du är inte riktigt direkt röra RAM någonsin i dina program. 200 00:16:34,190 --> 00:16:37,490 Om du tänker på det, hur jag ritade - 201 00:16:37,490 --> 00:16:44,330 Och faktiskt, om du går igenom GDB ser du samma sak. 202 00:16:51,120 --> 00:16:57,590 Oavsett hur många gånger du kör ditt program eller vilket program du kör, 203 00:16:57,590 --> 00:16:59,950 stapeln kommer alltid att starta - 204 00:16:59,950 --> 00:17:06,510 du alltid kommer att se variabler runt adress oxbffff något. 205 00:17:06,510 --> 00:17:09,470 Det är oftast någonstans i regionen. 206 00:17:09,470 --> 00:17:18,760 Men hur kan 2 program möjligen ha pekare till samma minne? 207 00:17:20,640 --> 00:17:27,650 [Elev] Det finns några godtyckliga beteckning där oxbfff är tänkt att vara på RAM 208 00:17:27,650 --> 00:17:31,320 som faktiskt kan vara på olika platser beroende på när funktionen hette. 209 00:17:31,320 --> 00:17:35,920 Ja. Termen är virtuellt minne. 210 00:17:35,920 --> 00:17:42,250 Tanken är att varje enskild process, varenda program som körs på din dator 211 00:17:42,250 --> 00:17:49,450 har sin egen - låt oss anta 32 bitar - helt oberoende adress utrymme. 212 00:17:49,450 --> 00:17:51,590 Detta är adressutrymmet. 213 00:17:51,590 --> 00:17:56,220 Den har sina egna helt oberoende 4 gigabyte att använda. 214 00:17:56,220 --> 00:18:02,220 >> Så om du kör 2 program samtidigt, ser detta program 4 gigabyte till sig själv, 215 00:18:02,220 --> 00:18:04,870 Programmet ser 4 gigabyte till sig själv, 216 00:18:04,870 --> 00:18:07,720 och det är omöjligt för detta program dereference en pekare 217 00:18:07,720 --> 00:18:10,920 och sluta med minne från detta program. 218 00:18:10,920 --> 00:18:18,200 Och vad virtuellt minne är en avbildning av en processer adressutrymme 219 00:18:18,200 --> 00:18:20,470 faktiska saker på RAM. 220 00:18:20,470 --> 00:18:22,940 Så det är upp till ditt operativsystem för att veta att, 221 00:18:22,940 --> 00:18:28,080 hey, när den här killen dereferences pekare oxbfff, som egentligen betyder 222 00:18:28,080 --> 00:18:31,040 att han vill RAM-byte 1000, 223 00:18:31,040 --> 00:18:38,150 medan om det här programmet dereferences oxbfff vill han verkligen RAM byte 10000. 224 00:18:38,150 --> 00:18:41,590 De kan vara godtyckligt långt ifrån varandra. 225 00:18:41,590 --> 00:18:48,730 Detta är även sant för saker i en enda processer adress utrymme. 226 00:18:48,730 --> 00:18:54,770 Så som det ser alla 4 gigabyte till sig själv, men låt oss säga - 227 00:18:54,770 --> 00:18:57,290 [Eleven] Har varje process - 228 00:18:57,290 --> 00:19:01,350 Låt oss säga att du har en dator med endast 4 gigabyte RAM-minne. 229 00:19:01,350 --> 00:19:06,430 Ser varenda process hela 4 gigabyte? >> Ja. 230 00:19:06,430 --> 00:19:13,060 Men de 4 gigabyte är det ser är en lögn. 231 00:19:13,060 --> 00:19:20,460 Det är bara den tycker att det har allt detta minne eftersom den inte känner någon annan process finns. 232 00:19:20,460 --> 00:19:28,140 Det kommer bara använda så mycket minne som den faktiskt behöver. 233 00:19:28,140 --> 00:19:32,340 Operativsystemet kommer inte att ge RAM-minne till denna process 234 00:19:32,340 --> 00:19:35,750 om den inte använder något minne i hela regionen. 235 00:19:35,750 --> 00:19:39,300 Det kommer inte att ge det minne för denna region. 236 00:19:39,300 --> 00:19:54,780 Men tanken är att - Jag försöker att tänka på - jag kan inte tänka en analogi. 237 00:19:54,780 --> 00:19:56,780 Analogier är svåra. 238 00:19:57,740 --> 00:20:02,700 En av de frågor som virtuellt minne eller en av de saker det lösa 239 00:20:02,700 --> 00:20:06,810 är att processerna ska vara helt omedvetna om varandra. 240 00:20:06,810 --> 00:20:12,140 Och så kan du skriva ett program som dereferences bara några pekare, 241 00:20:12,140 --> 00:20:19,340 precis skriva ett program som säger * (ox1234) 242 00:20:19,340 --> 00:20:22,890 och det är dereferencing minnesadress 1234. 243 00:20:22,890 --> 00:20:28,870 >> Men det är upp till operativsystemet för att sedan översätta vad 1234 betyder. 244 00:20:28,870 --> 00:20:33,960 Så om 1234 råkar vara en giltig minnesadress för denna process, 245 00:20:33,960 --> 00:20:38,800 som det är på stacken eller något, så kommer detta att returnera värdet på minnesadress 246 00:20:38,800 --> 00:20:41,960 såvitt processen vet. 247 00:20:41,960 --> 00:20:47,520 Men om 1234 är inte en giltig adress, som det händer att landa 248 00:20:47,520 --> 00:20:52,910 i någon liten bit av minnet här som är bortom stacken och bortom högen 249 00:20:52,910 --> 00:20:57,200 och du har inte riktigt använt det, så är det när du får saker som segfaults 250 00:20:57,200 --> 00:21:00,260 eftersom du rör minne som du inte bör röra. 251 00:21:07,180 --> 00:21:09,340 Detta är också sant - 252 00:21:09,340 --> 00:21:15,440 En 32-bitars system innebär 32 bitar har du 32 bitar för att definiera en minnesadress. 253 00:21:15,440 --> 00:21:22,970 Det är därför pekare är 8 byte eftersom 32 bitar 8 byte - eller 4 byte. 254 00:21:22,970 --> 00:21:25,250 Pekare är 4 byte. 255 00:21:25,250 --> 00:21:33,680 Så när du ser en pekare som oxbfffff, är det - 256 00:21:33,680 --> 00:21:40,080 Inom ett visst program kan du bara bygga ett godtyckligt pekare, 257 00:21:40,080 --> 00:21:46,330 allt från ox0 till ox 8 f's - FFFFFFFF. 258 00:21:46,330 --> 00:21:49,180 [Elev] Sa du inte att de är 4 byte? >> Ja. 259 00:21:49,180 --> 00:21:52,730 [Elev] Sedan varje byte har - >> [Bowden] Hexadecimal. 260 00:21:52,730 --> 00:21:59,360 Hexadecimalt - 5, 6, 7, 8. Så pekare du ska alltid se i hexadecimalt. 261 00:21:59,360 --> 00:22:01,710 Det är bara hur vi klassificerar pekare. 262 00:22:01,710 --> 00:22:05,240 Varje 2 siffrorna i hexadecimal är 1 byte. 263 00:22:05,240 --> 00:22:09,600 Så det kommer att bli 8 hexadecimala siffror för 4 byte. 264 00:22:09,600 --> 00:22:14,190 Så varje enskild pekaren på en 32-bitars system kommer att vara 4 byte, 265 00:22:14,190 --> 00:22:18,550 vilket innebär att i processen kan du bygga godtyckliga 4 byte 266 00:22:18,550 --> 00:22:20,550 och gör en pekare av det, 267 00:22:20,550 --> 00:22:32,730 vilket innebär att så långt det är vet, det kan ta en hel 2 till 32 byte minne. 268 00:22:32,730 --> 00:22:34,760 Även om det egentligen inte har tillgång till det, 269 00:22:34,760 --> 00:22:40,190 även om din dator bara har 512 megabyte, tycker att det har så mycket minne. 270 00:22:40,190 --> 00:22:44,930 Och operativsystemet är smart nog att det bara kommer att fördela vad du faktiskt behöver. 271 00:22:44,930 --> 00:22:49,630 Det är inte bara gå, åh, en ny process: 4 spelningar. 272 00:22:49,630 --> 00:22:51,930 >> Ja. >> [Elev] Vad oxen menar? Varför skriver du det? 273 00:22:51,930 --> 00:22:54,980 Det är bara en symbol för hexadecimala. 274 00:22:54,980 --> 00:22:59,590 När du ser ett nummer börjar med oxe, de successiva saker är hexadecimala. 275 00:23:01,930 --> 00:23:05,760 [Elev] Du var förklara om vad som händer när ett program avslutas. >> Ja. 276 00:23:05,760 --> 00:23:09,480 Vad händer när ett program avslutas är operativsystemet 277 00:23:09,480 --> 00:23:13,600 bara raderar avbildningar som den har för dessa adresser, och det är det. 278 00:23:13,600 --> 00:23:17,770 Operativsystemet kan nu bara ge det minnet till ett annat program att använda. 279 00:23:17,770 --> 00:23:19,490 [Elev] Okej. 280 00:23:19,490 --> 00:23:24,800 Så när du fördela något på heapen eller stacken eller globala variabler eller något, 281 00:23:24,800 --> 00:23:27,010 de alla bara försvinna så fort programmet avslutas 282 00:23:27,010 --> 00:23:32,120 eftersom operativsystemet är nu fri att ge det minnet till någon annan process. 283 00:23:32,120 --> 00:23:35,150 [Elev] Även om det finns förmodligen fortfarande värden skrivna i? >> Ja. 284 00:23:35,150 --> 00:23:37,740 Värdena är sannolikt kvar. 285 00:23:37,740 --> 00:23:41,570 Det är bara att det kommer att bli svårt att komma åt dem. 286 00:23:41,570 --> 00:23:45,230 Det är mycket svårare att komma åt dem än det är att få till en raderad fil 287 00:23:45,230 --> 00:23:51,450 eftersom den borttagna filen typ av sitter där under en lång tid och hårddisken är mycket större. 288 00:23:51,450 --> 00:23:54,120 Så det kommer att skriva över olika delar av minnet 289 00:23:54,120 --> 00:23:58,640 innan det händer att skriva över bit av minnet som filen används för att vara på. 290 00:23:58,640 --> 00:24:04,520 Men huvudminnet, RAM, du igenom mycket snabbare, 291 00:24:04,520 --> 00:24:08,040 så det kommer att mycket snabbt skrivas över. 292 00:24:10,300 --> 00:24:13,340 Frågor om detta eller något annat? 293 00:24:13,340 --> 00:24:16,130 [Eleven] Jag har frågor om ett annat ämne. >> Okej. 294 00:24:16,130 --> 00:24:19,060 Har någon frågor om detta? 295 00:24:20,170 --> 00:24:23,120 >> Okej. Annat ämne. >> [Elev] Okej. 296 00:24:23,120 --> 00:24:26,550 Jag gick igenom några av de praktiska testerna, 297 00:24:26,550 --> 00:24:30,480 och i en av dem det talade om sizeof 298 00:24:30,480 --> 00:24:35,630 och det värde som returneras eller olika variabeltyper. >> Ja. 299 00:24:35,630 --> 00:24:45,060 Och det sägs att både int och långa både retur 4, så de är båda 4 byte lång. 300 00:24:45,060 --> 00:24:48,070 Är det någon skillnad mellan en int och en lång, eller är det samma sak? 301 00:24:48,070 --> 00:24:50,380 Ja, det finns en skillnad. 302 00:24:50,380 --> 00:24:52,960 C-standarden - 303 00:24:52,960 --> 00:24:54,950 Jag kommer förmodligen att röra upp. 304 00:24:54,950 --> 00:24:58,800 C-standarden är precis vad C är den officiella dokumentationen av C. 305 00:24:58,800 --> 00:25:00,340 Detta är vad den säger. 306 00:25:00,340 --> 00:25:08,650 Så C-standard säger bara att en röding kommer alltid och alltid vara 1 byte. 307 00:25:10,470 --> 00:25:19,040 Allt efter att - en kort är alltid bara definieras som större än eller lika med en char. 308 00:25:19,040 --> 00:25:23,010 Detta kan vara strikt större än, men inte positivt. 309 00:25:23,010 --> 00:25:31,940 En int är precis definieras som större än eller lika med en kort. 310 00:25:31,940 --> 00:25:36,210 Och en lång är bara definieras som större än eller lika med en int. 311 00:25:36,210 --> 00:25:41,600 Och en lång lång är större än eller lika med en lång. 312 00:25:41,600 --> 00:25:46,610 Så det enda C-standarden definierar den relativa beställning av allt. 313 00:25:46,610 --> 00:25:54,880 Den faktiska mängden minne som saker tar upp är i allmänhet upp till genomförande, 314 00:25:54,880 --> 00:25:57,640 men det är ganska väl definierade vid denna punkt. >> [Elev] Okej. 315 00:25:57,640 --> 00:26:02,490 Så shorts är nästan alltid kommer att vara 2 byte. 316 00:26:04,920 --> 00:26:09,950 Ints är nästan alltid kommer att vara 4 byte. 317 00:26:12,070 --> 00:26:15,340 Långa longs är nästan alltid kommer att vara 8 byte. 318 00:26:17,990 --> 00:26:23,160 Och längtar, det beror på om du använder en 32-bitars eller en 64-bitars system. 319 00:26:23,160 --> 00:26:27,450 Så länge kommer att motsvara den typ av system. 320 00:26:27,450 --> 00:26:31,920 Om du använder en 32-bitars system som apparaten kommer det att bli 4 byte. 321 00:26:34,530 --> 00:26:42,570 Om du använder en 64-bitars som många nya datorer, det kommer att bli 8 byte. 322 00:26:42,570 --> 00:26:45,230 >> Ints är nästan alltid 4 byte på denna punkt. 323 00:26:45,230 --> 00:26:47,140 Långa longs är nästan alltid 8 byte. 324 00:26:47,140 --> 00:26:50,300 Förr i tiden använde ints att endast vara 2 byte. 325 00:26:50,300 --> 00:26:56,840 Men märker att detta helt uppfyller alla dessa relationer är större än och lika med. 326 00:26:56,840 --> 00:27:01,280 Så länge är perfekt får vara samma storlek som ett heltal, 327 00:27:01,280 --> 00:27:04,030 och det är också tillåtet att ha samma storlek som en lång lång. 328 00:27:04,030 --> 00:27:11,070 Och det råkar vara så att det i 99,999% av systemen, kommer det att vara lika med 329 00:27:11,070 --> 00:27:15,800 antingen en int eller en lång lång. Det beror bara på 32-bitars eller 64-bitars. >> [Elev] Okej. 330 00:27:15,800 --> 00:27:24,600 I flyter, hur är decimaltecknet utsetts i termer av bitar? 331 00:27:24,600 --> 00:27:27,160 Liksom som binär? >> Ja. 332 00:27:27,160 --> 00:27:30,570 Du behöver inte känna till att för CS50. 333 00:27:30,570 --> 00:27:32,960 Du behöver inte ens veta att under 61. 334 00:27:32,960 --> 00:27:37,350 Du lär inte som verkligen i någon kurs. 335 00:27:37,350 --> 00:27:42,740 Det är bara en representation. 336 00:27:42,740 --> 00:27:45,440 Jag glömmer den exakta bit kolonilotter. 337 00:27:45,440 --> 00:27:53,380 Idén med flyttal är att man tilldela ett visst antal bitar för att representera - 338 00:27:53,380 --> 00:27:56,550 I grunden är allt i grundpotensform. 339 00:27:56,550 --> 00:28:05,600 Så du tilldela ett visst antal bitar för att representera själva numret, som 1,2345. 340 00:28:05,600 --> 00:28:10,200 Jag kan aldrig representera ett tal med fler siffror än 5. 341 00:28:12,200 --> 00:28:26,300 Sedan kan du tilldela även ett visst antal bitar så att det tenderar att vara som 342 00:28:26,300 --> 00:28:32,810 du kan bara gå upp till ett visst antal, som det är den största exponenten du kan ha, 343 00:28:32,810 --> 00:28:36,190 och du kan bara gå ner till en viss exponent, 344 00:28:36,190 --> 00:28:38,770 gillar det är det minsta exponenten du kan ha. 345 00:28:38,770 --> 00:28:44,410 >> Jag minns inte exakt hur bitarna tilldelas alla dessa värden, 346 00:28:44,410 --> 00:28:47,940 men ett visst antal bitar är dedikerade till 1,2345, 347 00:28:47,940 --> 00:28:50,930 annat visst antal bitar är dedikerade till exponenten, 348 00:28:50,930 --> 00:28:55,670 och det är endast möjligt att representera en exponent av en viss storlek. 349 00:28:55,670 --> 00:29:01,100 [Elev] och en dubbel? Är det som en extra lång flyta? >> Ja. 350 00:29:01,100 --> 00:29:07,940 Det är samma sak som ett flöte än nu du använder 8 byte istället för 4 byte. 351 00:29:07,940 --> 00:29:11,960 Nu kommer du att kunna använda 9 siffror eller 10 siffror, 352 00:29:11,960 --> 00:29:16,630 och detta kommer att kunna gå upp till 300 istället för 100. >> [Elev] Okej. 353 00:29:16,630 --> 00:29:21,550 Och flyter är också 4 byte. >> Ja. 354 00:29:21,550 --> 00:29:27,520 Nåväl, återigen, beror det förmodligen totalt på allmänna genomförandet, 355 00:29:27,520 --> 00:29:30,610 men flottörer är 4 byte, dubbel är 8. 356 00:29:30,610 --> 00:29:33,440 Dubbel kallas dubbel eftersom de är dubbelt så stor flyter. 357 00:29:33,440 --> 00:29:38,380 [Elev] Okej. Och finns det fördubblar dubbelt? >> Det finns inte. 358 00:29:38,380 --> 00:29:43,660 Jag tror - >> [elev] gillar långa Longs? >> Ja. Jag tror inte det. Ja. 359 00:29:43,660 --> 00:29:45,950 [Elev] På förra årets test var det en fråga om huvudfunktionen 360 00:29:45,950 --> 00:29:49,490 behöva vara en del av ditt program. 361 00:29:49,490 --> 00:29:52,310 Svaret var att det inte behöver vara en del av ditt program. 362 00:29:52,310 --> 00:29:55,100 I vilken situation? Det är vad jag såg. 363 00:29:55,100 --> 00:29:59,090 [Bowden] Det verkar - >> [elev] Vad situation? 364 00:29:59,090 --> 00:30:02,880 Har du problemet? >> [Eleven] Ja, jag kan definitivt dra upp den. 365 00:30:02,880 --> 00:30:07,910 Det behöver inte vara tekniskt, men i grunden är det kommer att bli. 366 00:30:07,910 --> 00:30:10,030 [Elev] Jag såg en på en annan år. 367 00:30:10,030 --> 00:30:16,220 Det var som Sant eller falskt: Ett giltigt - >> Åh, en c-fil.? 368 00:30:16,220 --> 00:30:18,790 . [Elev] någon C-filen måste ha - [både talar på en gång - obegripligt] 369 00:30:18,790 --> 00:30:21,120 Okej. Så det är separata. 370 00:30:21,120 --> 00:30:26,800 >> A. C. fil behöver bara innehålla funktioner. 371 00:30:26,800 --> 00:30:32,400 Du kan kompilera en fil i maskinkod, binär, vad som helst, 372 00:30:32,400 --> 00:30:36,620 utan att det är körbar ännu. 373 00:30:36,620 --> 00:30:39,420 En giltig körbar måste ha en huvudfunktion. 374 00:30:39,420 --> 00:30:45,460 Du kan skriva 100 funktioner i 1 fil men ingen viktigaste 375 00:30:45,460 --> 00:30:48,800 och sedan sammanställa det ner till binär, 376 00:30:48,800 --> 00:30:54,460 då du skriver en annan fil som bara har huvud men det kräver en massa av dessa funktioner 377 00:30:54,460 --> 00:30:56,720 I detta binär fil här. 378 00:30:56,720 --> 00:31:01,240 Och så när du gör den körbara, det är vad länken gör 379 00:31:01,240 --> 00:31:05,960 är det kombinerar dessa 2 binära filer till en körbar. 380 00:31:05,960 --> 00:31:11,400 Så en. C. filen inte behöver ha en huvuduppgift alls. 381 00:31:11,400 --> 00:31:19,220 Och på stora kod baser ser du tusentals. C filer och 1 huvudfil. 382 00:31:23,960 --> 00:31:26,110 Fler frågor? 383 00:31:29,310 --> 00:31:31,940 [Elev] Det var en annan fråga. 384 00:31:31,940 --> 00:31:36,710 Det sade att en kompilator. Sant eller falskt? 385 00:31:36,710 --> 00:31:42,030 Och svaret var falsk, och jag förstod varför det är inte som klang. 386 00:31:42,030 --> 00:31:44,770 Men vad kallar vi göra om det inte är? 387 00:31:44,770 --> 00:31:49,990 Göra är i princip bara - jag kan se exakt vad man kallar det. 388 00:31:49,990 --> 00:31:52,410 Men det går bara kommandon. 389 00:31:53,650 --> 00:31:55,650 Gör. 390 00:31:58,240 --> 00:32:00,870 Jag kan dra upp detta. Ja. 391 00:32:10,110 --> 00:32:13,180 Oh, ja. Gör gör också det. 392 00:32:13,180 --> 00:32:17,170 Detta säger syftet med märke verktyget är att fastställa automatiskt 393 00:32:17,170 --> 00:32:19,610 vilka delar av ett stort program behöver byggas 394 00:32:19,610 --> 00:32:22,350 och utfärda kommandon för att kompilera dem. 395 00:32:22,350 --> 00:32:27,690 Du kan göra göra filer som är helt enorm. 396 00:32:27,690 --> 00:32:33,210 Gör tittar på tidsstämplar av filer och som vi sagt tidigare, 397 00:32:33,210 --> 00:32:36,930 Du kan kompilera enskilda filer ned, och det är inte förrän du kommer till länken 398 00:32:36,930 --> 00:32:39,270 att de är tillsammans i en körbar. 399 00:32:39,270 --> 00:32:43,810 Så om du har 10 olika filer och du gör en ändring 1 av dem, 400 00:32:43,810 --> 00:32:47,870 vad märke kommer att göra är bara kompilera att 1 fil 401 00:32:47,870 --> 00:32:50,640 och sedan länka ihop allting. 402 00:32:50,640 --> 00:32:53,020 Men det är mycket dummare än så. 403 00:32:53,020 --> 00:32:55,690 Det är upp till dig att helt definiera att det är vad det borde göra. 404 00:32:55,690 --> 00:32:59,560 Den som standard har förmågan att känna igen det här tidsstämpel, 405 00:32:59,560 --> 00:33:03,220 men du kan skriva en märke fil att göra någonting. 406 00:33:03,220 --> 00:33:09,150 Du kan skriva en make-fil så att när du skriver att det bara cd-skivor till en annan katalog. 407 00:33:09,150 --> 00:33:15,560 Jag började bli frustrerad eftersom jag tack allt inuti mitt Appliance 408 00:33:15,560 --> 00:33:21,740 och då jag visa PDF från Mac. 409 00:33:21,740 --> 00:33:30,720 >> Så jag går till Finder och jag kan gå, Anslut till server, 410 00:33:30,720 --> 00:33:36,950 och servern jag ansluter till är min Appliance, och sedan jag öppnar PDF- 411 00:33:36,950 --> 00:33:40,190 som blir sammanställd av LaTeX. 412 00:33:40,190 --> 00:33:49,320 Men jag var att få frustrerad eftersom varje gång jag behövde uppdatera PDF 413 00:33:49,320 --> 00:33:53,900 Jag var tvungen att kopiera den till en specifik katalog att det kan komma 414 00:33:53,900 --> 00:33:57,710 och det var att få irriterande. 415 00:33:57,710 --> 00:34:02,650 Så istället skrev jag en make-fil som du måste definiera hur det gör saker och ting. 416 00:34:02,650 --> 00:34:06,130 Hur du gör detta är PDF LaTeX. 417 00:34:06,130 --> 00:34:10,090 Precis som alla andra fabrikat fil - eller jag antar att du inte har sett göra filer, 418 00:34:10,090 --> 00:34:13,510 men vi har i apparaten en global fabrikat fil som bara säger, 419 00:34:13,510 --> 00:34:16,679 Om du kompilerar en C-fil, använd klang. 420 00:34:16,679 --> 00:34:20,960 Och så här i min make fil som jag gör säger jag, 421 00:34:20,960 --> 00:34:25,020 den här filen som du kommer att vilja kompilera med PDF LaTeX. 422 00:34:25,020 --> 00:34:27,889 Och så är det PDF-latex som gör det kompilerar. 423 00:34:27,889 --> 00:34:31,880 Gör inte kompilera. Det är bara att köra dessa kommandon i sekvensen jag angett. 424 00:34:31,880 --> 00:34:36,110 Så det går PDF LaTeX, kopierar den till den katalog jag vill att den ska kopieras till, 425 00:34:36,110 --> 00:34:38,270 det CD till katalogen och gör andra saker, 426 00:34:38,270 --> 00:34:42,380 men allt den gör är igen när en fil ändras, 427 00:34:42,380 --> 00:34:45,489 och om det ändrar, så kommer det att köra kommandon som det är tänkt att köra 428 00:34:45,489 --> 00:34:48,760 när filen ändras. >> [Elev] Okej. 429 00:34:50,510 --> 00:34:54,420 Jag vet inte var de globala göra filer är för mig att kolla upp det. 430 00:34:57,210 --> 00:35:04,290 Övriga frågor? Allt från tidigare frågesporter? Eventuella pekaren saker? 431 00:35:06,200 --> 00:35:08,730 Det finns subtila saker med pekare som - 432 00:35:08,730 --> 00:35:10,220 Jag tänker inte att kunna hitta en frågesport fråga på det - 433 00:35:10,220 --> 00:35:16,250 men precis som den här sortens saker. 434 00:35:19,680 --> 00:35:24,060 Se till att du förstår att när jag säger int * x * y - 435 00:35:24,890 --> 00:35:28,130 Det är inte precis något här, antar jag. 436 00:35:28,130 --> 00:35:32,140 Men precis * x * y, de är 2 variabler som är på stacken. 437 00:35:32,140 --> 00:35:37,220 När jag säger x = malloc (sizeof (int)), x fortfarande en variabel på stacken, 438 00:35:37,220 --> 00:35:41,180 malloc är några kvarter över i högen, och vi ska ha X pekar på högen. 439 00:35:41,180 --> 00:35:43,900 >> Så något på stacken pekar på högen. 440 00:35:43,900 --> 00:35:48,100 När du malloc någonting, du lagrar oundvikligen det inne i en pekare. 441 00:35:48,100 --> 00:35:55,940 Så att pekaren är på stacken, är det malloced blocket på högen. 442 00:35:55,940 --> 00:36:01,240 Många människor blir förvirrade och säga int * x = malloc, x är på högen. 443 00:36:01,240 --> 00:36:04,100 Nej Vad X pekar är på högen. 444 00:36:04,100 --> 00:36:08,540 X själv är på stacken, såvida du av någon anledning har X vara en global variabel, 445 00:36:08,540 --> 00:36:11,960 i vilket fall det råkar vara i en annan region av minnet. 446 00:36:13,450 --> 00:36:20,820 Så hålla reda dessa box och pil diagram är ganska vanligt att testet. 447 00:36:20,820 --> 00:36:25,740 Eller om det inte är på frågesport 0, kommer det att vara på frågesport 1. 448 00:36:27,570 --> 00:36:31,940 Du bör känna alla dessa stegen i att sammanställa 449 00:36:31,940 --> 00:36:35,740 eftersom du var tvungen att svara på frågor om dem. Ja. 450 00:36:35,740 --> 00:36:38,940 [Elev] Kan vi gå över dessa steg - >> Visst. 451 00:36:48,340 --> 00:36:58,640 Innan steg och sammanställa vi förbehandling, 452 00:36:58,640 --> 00:37:16,750 sammanställa, montering och länkning. 453 00:37:16,750 --> 00:37:21,480 Förbehandling. Vad gör det? 454 00:37:29,720 --> 00:37:32,290 Det är det enklaste steget i - ja, inte som - 455 00:37:32,290 --> 00:37:35,770 det betyder inte att det borde vara självklart, men det är det enklaste steget. 456 00:37:35,770 --> 00:37:38,410 Ni skulle kunna genomföra det själva. Ja. 457 00:37:38,410 --> 00:37:43,410 [Elev] Ta vad du har i ditt omfattar så här och det kopieras och sedan också definierar. 458 00:37:43,410 --> 00:37:49,250 Det ser för saker som # include och # define, 459 00:37:49,250 --> 00:37:53,800 och det bara kopior och pastor vad de betyder egentligen. 460 00:37:53,800 --> 00:37:59,240 Så när du säger # include cs50.h är preprocessorn kopiera och klistra in cs50.h 461 00:37:59,240 --> 00:38:01,030 till den linjen. 462 00:38:01,030 --> 00:38:06,640 När du säger # define X är 4 går preprocessorn genom hela programmet 463 00:38:06,640 --> 00:38:10,400 och ersätter alla förekomster av x med 4. 464 00:38:10,400 --> 00:38:17,530 Så preprocessorn tar en giltig C-fil och matar en giltig C-fil 465 00:38:17,530 --> 00:38:20,300 där saker har kopierats och klistrats. 466 00:38:20,300 --> 00:38:24,230 Så nu sammanställa. Vad gör det? 467 00:38:25,940 --> 00:38:28,210 [Elev] Det går från C till binärt. 468 00:38:28,210 --> 00:38:30,970 >> [Bowden] Det går inte hela vägen till binära. 469 00:38:30,970 --> 00:38:34,220 [Elev] till maskinkod då? >> Det är inte maskinkod. 470 00:38:34,220 --> 00:38:35,700 [Eleven] Montering? >> Församling. 471 00:38:35,700 --> 00:38:38,890 Det går att församlingen innan den går hela vägen till C-kod, 472 00:38:38,890 --> 00:38:45,010 och de flesta språken göra något liknande. 473 00:38:47,740 --> 00:38:50,590 Välj en högnivåspråk, och om du ska kompilera, 474 00:38:50,590 --> 00:38:52,390 det är sannolikt att kompilera i steg. 475 00:38:52,390 --> 00:38:58,140 Först det kommer att kompilera Python till C, då det kommer att sammanställa C församling, 476 00:38:58,140 --> 00:39:01,600 och därefter församlingen kommer att få översatt till binär. 477 00:39:01,600 --> 00:39:07,800 Så sammanställa kommer att få det från C till församlingen. 478 00:39:07,800 --> 00:39:12,130 Ordet sammanställa betyder oftast att föra det från en högre nivå 479 00:39:12,130 --> 00:39:14,340 till en lägre nivå programmeringsspråk. 480 00:39:14,340 --> 00:39:19,190 Så detta är den enda steg i sammanställningen där du börjar med en högnivåspråk 481 00:39:19,190 --> 00:39:23,270 och hamna i en låg nivå språk, och det är därför steget kallas kompilering. 482 00:39:25,280 --> 00:39:33,370 [Elev] Under sammanställa, låt oss säga att du har gjort # include cs50.h. 483 00:39:33,370 --> 00:39:42,190 Kommer kompilatorn kompilera om cs50.h, liksom de funktioner som finns i det, 484 00:39:42,190 --> 00:39:45,280 och översätta det till assemblerkod också, 485 00:39:45,280 --> 00:39:50,830 eller kommer det att kopiera och klistra in något som har varit förmontering? 486 00:39:50,830 --> 00:39:56,910 cs50.h kommer ganska mycket aldrig hamna i församlingen. 487 00:39:59,740 --> 00:40:03,680 Saker som funktion prototyper och saker är bara för dig att vara försiktig. 488 00:40:03,680 --> 00:40:09,270 Den garanterar att kompilatorn kan kontrollera saker som du ringer funktioner 489 00:40:09,270 --> 00:40:12,910 med rätt avkastning typer och de rätta argumenten och sånt. 490 00:40:12,910 --> 00:40:18,350 >> Så cs50.h ska förbehandlas i filen, och sedan när det sammanställa 491 00:40:18,350 --> 00:40:22,310 Det är i princip kastas bort efter det ser till att allt anropas korrekt. 492 00:40:22,310 --> 00:40:29,410 Men de funktioner som definieras i CS50 biblioteket, som är skild från cs50.h, 493 00:40:29,410 --> 00:40:33,610 de kommer inte separat sammanställas. 494 00:40:33,610 --> 00:40:37,270 Som faktiskt kommer att komma ner i den länkande steget, så vi kommer till det på en sekund. 495 00:40:37,270 --> 00:40:40,100 Men först, vad montering? 496 00:40:41,850 --> 00:40:44,500 [Eleven] församlingen binärt? >> Ja. 497 00:40:46,300 --> 00:40:48,190 Montering. 498 00:40:48,190 --> 00:40:54,710 Vi kallar det inte kompilera eftersom församling är ganska mycket en ren översättning av binära. 499 00:40:54,710 --> 00:41:00,230 Det finns mycket lite logik i att gå från församlingen binärt. 500 00:41:00,230 --> 00:41:03,180 Det är precis som tittar upp i en tabell, åh, vi har denna instruktion; 501 00:41:03,180 --> 00:41:06,290 som motsvarar binära 01.110. 502 00:41:10,200 --> 00:41:15,230 Och så de filer som montering generellt utgångar är. O-filer. 503 00:41:15,230 --> 00:41:19,020 Och. O-filer är vad vi sade tidigare, 504 00:41:19,020 --> 00:41:21,570 hur en fil inte behöver ha en huvuduppgift. 505 00:41:21,570 --> 00:41:27,640 Alla filer kan sammanställas ner till en. O. fil så länge det är en giltig C-fil. 506 00:41:27,640 --> 00:41:30,300 Det kan kompileras ner till. O.. 507 00:41:30,300 --> 00:41:43,030 Nu kopplar vad som faktiskt ger ett gäng. O filer och ger dem till en körbar. 508 00:41:43,030 --> 00:41:51,110 Och så vad länkning gör är att du kan tänka på CS50 biblioteket som en. O. fil. 509 00:41:51,110 --> 00:41:56,980 Det är en redan kompilerad binär fil. 510 00:41:56,980 --> 00:42:03,530 Och så när du bygger din fil, din hej.c, som kallar GetString, 511 00:42:03,530 --> 00:42:06,360 hej.c får sammanställt ner till hello.o, 512 00:42:06,360 --> 00:42:08,910 hello.o är nu i binär. 513 00:42:08,910 --> 00:42:12,830 Den använder GetString, så det måste gå över till cs50.o, 514 00:42:12,830 --> 00:42:16,390 och länken smooshes ihop dem och kopierar GetString i den här filen 515 00:42:16,390 --> 00:42:20,640 och kommer ut med en körbar som har alla funktioner man behöver. 516 00:42:20,640 --> 00:42:32,620 Så cs50.o är egentligen inte en O-fil, men det är nära nog att det inte finns någon grundläggande skillnad. 517 00:42:32,620 --> 00:42:36,880 Så koppla bara ger en massa filer tillsammans 518 00:42:36,880 --> 00:42:41,390 som separat innehåller alla funktioner jag behöver använda 519 00:42:41,390 --> 00:42:46,120 och skapar körbara som faktiskt kommer att köras. 520 00:42:48,420 --> 00:42:50,780 >> Och så det är också vad vi sade innan 521 00:42:50,780 --> 00:42:55,970 där du kan få 1000. c-filer, sammanställa du dem alla till. o-filer, 522 00:42:55,970 --> 00:43:00,040 som sannolikt kommer att ta ett tag, sedan ändrar 1. c. fil. 523 00:43:00,040 --> 00:43:05,480 Du behöver bara kompilera att 1. C. fil och sedan länka allt annat, 524 00:43:05,480 --> 00:43:07,690 länka allting tillsammans igen. 525 00:43:09,580 --> 00:43:11,430 [Elev] När vi länkar vi skriver lcs50? 526 00:43:11,430 --> 00:43:20,510 Ja, så lcs50. Att flagga signaler till länken som du bör länka i biblioteket. 527 00:43:26,680 --> 00:43:28,910 Frågor? 528 00:43:41,310 --> 00:43:46,860 Har vi gått över binär annat än att 5 sekunder i den första föreläsningen? 529 00:43:50,130 --> 00:43:53,010 Jag tror inte det. 530 00:43:55,530 --> 00:43:58,820 Du bör känna alla de stora operativsystem som vi har gått över, 531 00:43:58,820 --> 00:44:02,670 och du bör kunna, om vi gav dig en funktion, 532 00:44:02,670 --> 00:44:09,410 Du ska kunna säga att det är Big O, ungefär. Eller också är Big O grov. 533 00:44:09,410 --> 00:44:15,300 Så om du ser kapslade för slingor loopa över samma antal saker, 534 00:44:15,300 --> 00:44:22,260 Liksom int i, i > [elev] n kvadrat. >> Det tenderar att vara n kvadrat. 535 00:44:22,260 --> 00:44:25,280 Om du har trippel kapslade, tenderar det att vara n kubik. 536 00:44:25,280 --> 00:44:29,330 Så sånt ska du kunna peka ut omedelbart. 537 00:44:29,330 --> 00:44:33,890 Du behöver veta införande sortera och bubbla sortera och sammanfoga sortera och alla dessa. 538 00:44:33,890 --> 00:44:41,420 Det är lättare att förstå varför de är de n fyrkantiga och n log n och allt det 539 00:44:41,420 --> 00:44:47,810 eftersom jag tror att det var på en frågesport ett år där vi i princip gav dig 540 00:44:47,810 --> 00:44:55,050 en implementering av bubbla sortera och sade: "Vad är körtiden för denna funktion?" 541 00:44:55,050 --> 00:45:01,020 Så om du känner igen det som bubbla sortera, då kan du omedelbart säga N kvadrat. 542 00:45:01,020 --> 00:45:05,470 Men om du bara ser på det, behöver du inte ens behöver inse att det är bubbla Sortera; 543 00:45:05,470 --> 00:45:08,990 Du kan bara säga detta gör detta och detta. Detta är n kvadrat. 544 00:45:12,350 --> 00:45:14,710 [Elev] Finns det några tuffa exempel du kan komma med, 545 00:45:14,710 --> 00:45:20,370 som en liknande idé att räkna ut? 546 00:45:20,370 --> 00:45:24,450 >> Jag tror inte att vi skulle ge dig några tuffa exempel. 547 00:45:24,450 --> 00:45:30,180 Bubblan Sortera sak är ungefär lika tuff som vi skulle gå, 548 00:45:30,180 --> 00:45:36,280 och även att, så länge du förstår att du iteration över arrayen 549 00:45:36,280 --> 00:45:41,670 för varje element i arrayen, vilket kommer att vara något som är n kvadrat. 550 00:45:45,370 --> 00:45:49,940 Det finns allmänna frågor, som just här vi har - Oh. 551 00:45:55,290 --> 00:45:58,530 Häromdagen, Doug hävdade: "Jag har uppfunnit en algoritm som kan sortera en array 552 00:45:58,530 --> 00:46:01,780 "Av n tal i O (log n) tid!" 553 00:46:01,780 --> 00:46:04,900 Så hur vet vi att det är omöjligt? 554 00:46:04,900 --> 00:46:08,850 [Ohörbart elev svar] >> Ja. 555 00:46:08,850 --> 00:46:13,710 Åtminstone måste du röra varje element i arrayen, 556 00:46:13,710 --> 00:46:16,210 så det är omöjligt att sortera en array av - 557 00:46:16,210 --> 00:46:20,850 Om allt är i osorterat ordning, då du kommer att röra allt i arrayen, 558 00:46:20,850 --> 00:46:25,320 så det är omöjligt att göra det på mindre än O n. 559 00:46:27,430 --> 00:46:30,340 [Elev] Du visade oss att exempel att kunna göra det i O n 560 00:46:30,340 --> 00:46:33,920 om du använder mycket minne. >> Ja. 561 00:46:33,920 --> 00:46:37,970 Och that - jag har glömt vad that - Är det räknar slag? 562 00:46:47,360 --> 00:46:51,330 Hmm. Det är ett heltal sortering algoritm. 563 00:46:59,850 --> 00:47:05,100 Jag letade efter det särskilda namnet för att jag inte kunde minnas förra veckan. 564 00:47:05,100 --> 00:47:13,000 Ja. Dessa är de typer av slag som kan utföra saker i Big O n. 565 00:47:13,000 --> 00:47:18,430 Men det finns begränsningar, som du kan bara använda heltal upp till ett visst antal. 566 00:47:20,870 --> 00:47:24,560 Plus om du försöker sortera något that - 567 00:47:24,560 --> 00:47:30,750 Om din array är 012, -12, 151, 4 miljoner, 568 00:47:30,750 --> 00:47:35,120 då den enda element kommer att fullständigt förstöra hela sortering. 569 00:47:42,060 --> 00:47:44,030 >> Frågor? 570 00:47:49,480 --> 00:47:58,870 [Elev] Om du har en rekursiv funktion och det bara gör rekursiva anrop 571 00:47:58,870 --> 00:48:02,230 inom en return, det svansen rekursiv, 572 00:48:02,230 --> 00:48:07,360 och så skulle det inte använda mer minne under körning 573 00:48:07,360 --> 00:48:12,550 eller det skulle åtminstone använda jämförbara minne som en iterativ lösning? 574 00:48:12,550 --> 00:48:14,530 [Bowden] Ja. 575 00:48:14,530 --> 00:48:19,840 Det skulle sannolikt vara något långsammare, men inte riktigt. 576 00:48:19,840 --> 00:48:23,290 Svans rekursiv är ganska bra. 577 00:48:23,290 --> 00:48:32,640 Ser igen på stack ramar, låt oss säga att vi har stora 578 00:48:32,640 --> 00:48:42,920 och vi har int bar (int x) eller något. 579 00:48:42,920 --> 00:48:52,310 Detta är inte en perfekt rekursiv funktion, men retur bar (x - 1). 580 00:48:52,310 --> 00:48:57,620 Så uppenbarligen är detta bristfälliga. Du behöver bas ärenden och sånt. 581 00:48:57,620 --> 00:49:00,360 Men tanken här är att det är svansen rekursiv, 582 00:49:00,360 --> 00:49:06,020 vilket innebär att när stora samtal bar det kommer att få sin stack ram. 583 00:49:09,550 --> 00:49:12,440 I denna stack ram det kommer att vara lite block av minne 584 00:49:12,440 --> 00:49:17,490 som motsvarar dess argument x. 585 00:49:17,490 --> 00:49:25,840 Och så låt oss säga viktigaste råkar ringa bar (100); 586 00:49:25,840 --> 00:49:30,050 Så X kommer att börja som 100. 587 00:49:30,050 --> 00:49:35,660 Om kompilatorn är medveten om att detta är en svans rekursiv funktion, 588 00:49:35,660 --> 00:49:38,540 sedan när baren gör sin rekursivt anrop till bar, 589 00:49:38,540 --> 00:49:45,490 istället för att göra en ny stapel ram, som är där stapeln börjar växa stort, 590 00:49:45,490 --> 00:49:48,220 så småningom kommer att köra in i högen och sedan får du segfaults 591 00:49:48,220 --> 00:49:51,590 eftersom minnet börjar kolliderar. 592 00:49:51,590 --> 00:49:54,830 >> Så istället för att göra en egen stack ram, kan det inser, 593 00:49:54,830 --> 00:49:59,080 hej, jag har aldrig riktigt behöver komma tillbaka till denna stack ram, 594 00:49:59,080 --> 00:50:08,040 så istället ska jag bara ersätta detta argument med 99 och sedan börja bar överallt. 595 00:50:08,040 --> 00:50:11,810 Och så kommer det att göra det igen och det kommer att nå tillbaka bar (x - 1), 596 00:50:11,810 --> 00:50:17,320 och istället för att göra en ny stack ram kommer den att ersätta bara dess nuvarande argument med 98 597 00:50:17,320 --> 00:50:20,740 och sedan hoppa tillbaka till början av bar. 598 00:50:23,860 --> 00:50:30,430 Denna hantering, ersätter den 1 värde på stacken och hoppa tillbaka till början, 599 00:50:30,430 --> 00:50:32,430 är ganska effektiv. 600 00:50:32,430 --> 00:50:41,500 Så inte bara är detta samma minnesanvändningen som en separat funktion som iterativ 601 00:50:41,500 --> 00:50:45,390 eftersom du bara använder 1 stack ram, men du inte lider av nackdelar 602 00:50:45,390 --> 00:50:47,240 att behöva anropa funktioner. 603 00:50:47,240 --> 00:50:50,240 Samtalsfunktioner kan vara något dyrt eftersom det har att göra allt denna inställning 604 00:50:50,240 --> 00:50:52,470 och nedkoppling och allt det här. 605 00:50:52,470 --> 00:50:58,160 Så denna svans rekursion är bra. 606 00:50:58,160 --> 00:51:01,170 [Eleven] Varför inte skapa nya steg? 607 00:51:01,170 --> 00:51:02,980 Eftersom det inser att det inte behöver. 608 00:51:02,980 --> 00:51:07,800 Samtalet till bar är bara returnera rekursiva anropet. 609 00:51:07,800 --> 00:51:12,220 Så det behöver inte göra något med returvärdet. 610 00:51:12,220 --> 00:51:15,120 Det är bara att gå till omedelbart lämna tillbaka den. 611 00:51:15,120 --> 00:51:20,530 Så det är bara att byta ut sin egen argumentation och börja om. 612 00:51:20,530 --> 00:51:25,780 Och även om du inte har svans rekursiva versionen, 613 00:51:25,780 --> 00:51:31,460 då får du alla dessa barer där när denna bar returnerar 614 00:51:31,460 --> 00:51:36,010 den måste returnera dess värde till den här, då bar omedelbart tillbaka 615 00:51:36,010 --> 00:51:39,620 och den återgår dess värde till den här, då är det bara att omedelbart återlämna 616 00:51:39,620 --> 00:51:41,350 och returnera dess värde till den här. 617 00:51:41,350 --> 00:51:45,350 Så du sparar detta poppar alla dessa saker av stapeln 618 00:51:45,350 --> 00:51:48,730 eftersom returvärdet är bara kommer att föras hela vägen tillbaka upp ändå. 619 00:51:48,730 --> 00:51:55,400 Så varför inte bara ersätta vårt argument med den uppdaterade argument och börja om? 620 00:51:57,460 --> 00:52:01,150 Om funktionen inte är svans rekursiv, om du gör något liknande - 621 00:52:01,150 --> 00:52:07,530 [Elev] om bar (x + 1). >> Ja. 622 00:52:07,530 --> 00:52:11,770 >> Så om du lägger den i skick, då du gör något med returvärdet. 623 00:52:11,770 --> 00:52:16,260 Eller även om du bara gör retur 2 * bar (x - 1). 624 00:52:16,260 --> 00:52:23,560 Så nu bar (x - 1) måste återvända för att det att beräkna 2 gånger detta värde, 625 00:52:23,560 --> 00:52:26,140 så nu behöver en egen separat stack ram, 626 00:52:26,140 --> 00:52:31,180 och nu, oavsett hur mycket man än försöker, du kommer att behöva - 627 00:52:31,180 --> 00:52:34,410 Detta är inte svans rekursiv. 628 00:52:34,410 --> 00:52:37,590 [Elev] Skulle jag försöka få en rekursion för att sträva efter en svans rekursion - 629 00:52:37,590 --> 00:52:41,450 [Bowden] I en perfekt värld, men i CS50 du behöver inte. 630 00:52:43,780 --> 00:52:49,280 För att få svansen rekursion i allmänhet ställer du in ytterligare ett argument 631 00:52:49,280 --> 00:52:53,550 där bar tar int x till y 632 00:52:53,550 --> 00:52:56,990 och y motsvarar den ultimata sak du vill returnera. 633 00:52:56,990 --> 00:53:03,650 Så då detta du kommer att vara tillbaka bar (x - 1), 2 * y. 634 00:53:03,650 --> 00:53:09,810 Så det är bara en hög nivå hur man förvandlar saker att vara svans rekursiv. 635 00:53:09,810 --> 00:53:13,790 Men den extra argumentet - 636 00:53:13,790 --> 00:53:17,410 Och sedan i slutet när du når din bas fallet återvänder du bara y 637 00:53:17,410 --> 00:53:22,740 eftersom du har ackumulera hela tiden returvärdet som du vill. 638 00:53:22,740 --> 00:53:27,280 Du typ av har gjort det iterativt men med rekursiva anrop. 639 00:53:32,510 --> 00:53:34,900 Frågor? 640 00:53:34,900 --> 00:53:39,890 [Elev] Kanske om pekare aritmetik, som vid användning av strängar. >> Visst. 641 00:53:39,890 --> 00:53:43,610 Pointer aritmetik. 642 00:53:43,610 --> 00:53:48,440 När du använder strängar är det lätt eftersom strängarna är röding stjärnor, 643 00:53:48,440 --> 00:53:51,860 tecken är evigt och alltid en enda byte, 644 00:53:51,860 --> 00:53:57,540 och så visare aritmetik motsvarar vanlig aritmetik när du arbetar med strängar. 645 00:53:57,540 --> 00:54:08,790 Låt oss bara säga char * s = "hej". 646 00:54:08,790 --> 00:54:11,430 Så vi har ett block i minnet. 647 00:54:19,490 --> 00:54:22,380 Det behöver 6 byte eftersom du alltid behöver null avslutare. 648 00:54:22,380 --> 00:54:28,620 Och röding * s kommer att peka på början av denna uppsättning. 649 00:54:28,620 --> 00:54:32,830 Så är pekar där. 650 00:54:32,830 --> 00:54:36,710 Nu är det i princip hur en matris fungerar, 651 00:54:36,710 --> 00:54:40,780 oavsett om det var en avkastning genom malloc eller om det är på stacken. 652 00:54:40,780 --> 00:54:47,110 Varje matris är i grunden en pekare till början av arrayen, 653 00:54:47,110 --> 00:54:53,640 och sedan någon array funktion, varje indexering är bara att gå in i den matris en viss förskjutning. 654 00:54:53,640 --> 00:55:05,360 >> Så när jag säger något i stil med s [3], vilket kommer att s och räkna 3 tecken i. 655 00:55:05,360 --> 00:55:12,490 Så s [3], har vi 0, 1, 2, 3, så s [3] kommer att hänvisa till denna l.. 656 00:55:12,490 --> 00:55:20,460 [Elev] Och vi kunde nå samma värde genom att göra s + 3 och sedan parenteser stjärna? 657 00:55:20,460 --> 00:55:22,570 Ja. 658 00:55:22,570 --> 00:55:26,010 Detta är ekvivalent med * (s + 3); 659 00:55:26,010 --> 00:55:31,240 och det är för evigt och alltid lika oavsett vad du gör. 660 00:55:31,240 --> 00:55:34,070 Du behöver aldrig använda fästet syntaxen. 661 00:55:34,070 --> 00:55:37,770 Du kan alltid använda * (s + 3) syntax. 662 00:55:37,770 --> 00:55:40,180 Människor tenderar att vilja fästet syntaxen, dock. 663 00:55:40,180 --> 00:55:43,860 [Elev] Så alla matriser är faktiskt bara pekare. 664 00:55:43,860 --> 00:55:53,630 Det finns en liten skillnad när jag säger int x [4], >> [elev] Betyder det att skapa minnet? 665 00:55:53,630 --> 00:56:03,320 [Bowden] Det kommer att skapa 4 Ints på stacken, så 16 byte totalt. 666 00:56:03,320 --> 00:56:05,700 Det kommer att skapa 16 byte på stacken. 667 00:56:05,700 --> 00:56:09,190 X lagras inte någonstans. 668 00:56:09,190 --> 00:56:13,420 Det är bara en symbol som hänvisar till början av saken. 669 00:56:13,420 --> 00:56:17,680 Eftersom du förklarade matrisen inuti denna funktion, 670 00:56:17,680 --> 00:56:22,340 vad kompilatorn kommer att göra är att byta ut bara alla förekomster av variabeln x 671 00:56:22,340 --> 00:56:26,400 med där det hände att välja att sätta dessa 16 byte. 672 00:56:26,400 --> 00:56:30,040 Det kan inte göra det med char * s eftersom s är en verklig pekare. 673 00:56:30,040 --> 00:56:32,380 Det är gratis att sedan peka på andra saker. 674 00:56:32,380 --> 00:56:36,140 x är en konstant. Du kan inte ha det pekar på en annan array. >> [Elev] Okej. 675 00:56:36,140 --> 00:56:43,420 Men denna idé, denna indexering, är densamma oavsett om det är en traditionell uppsättning 676 00:56:43,420 --> 00:56:48,230 eller om det är en pekare till något eller om det är en pekare till en malloced array. 677 00:56:48,230 --> 00:56:59,770 Och i själva verket är det så likvärdigt att det är också samma sak. 678 00:56:59,770 --> 00:57:05,440 Det faktiskt bara översätter vad som finns inuti av fästena och vad som är kvar av konsolerna, 679 00:57:05,440 --> 00:57:07,970 lägger till dem tillsammans och dereferences. 680 00:57:07,970 --> 00:57:14,710 Så detta är lika giltiga som * (s + 3) eller s [3]. 681 00:57:16,210 --> 00:57:22,090 [Elev] Kan du pekare som pekar till 2-dimensionella arrayer? 682 00:57:22,090 --> 00:57:27,380 >> Det är svårare. Traditionellt, nr. 683 00:57:27,380 --> 00:57:34,720 En 2-dimensionell array är bara en 1-dimensionell array med någon lämplig syntax 684 00:57:34,720 --> 00:57:54,110 för när jag säger int x [3] [3], det här är egentligen bara 1 array med 9 värden. 685 00:57:55,500 --> 00:58:03,000 Och så när jag index vet kompilatorn vad jag menar. 686 00:58:03,000 --> 00:58:13,090 Om jag säger x [1] [2], vet det Jag vill gå till den andra raden, så det kommer att hoppa över den första 3, 687 00:58:13,090 --> 00:58:17,460 och sedan vill den andra saken genom att, så det kommer att bli här. 688 00:58:17,460 --> 00:58:20,480 Men det är fortfarande bara en enda endimensionell matris. 689 00:58:20,480 --> 00:58:23,660 Och så om jag ville ge en pekare till den arrayen, 690 00:58:23,660 --> 00:58:29,770 Jag skulle säga int * p = x; 691 00:58:29,770 --> 00:58:33,220 Den typ av x är bara - 692 00:58:33,220 --> 00:58:38,280 Det är grov säger typ av x eftersom det är bara en symbol och det är inte en faktisk variabel, 693 00:58:38,280 --> 00:58:40,140 men det är bara en int *. 694 00:58:40,140 --> 00:58:44,840 x är bara en pekare till början av detta. >> [Elev] Okej. 695 00:58:44,840 --> 00:58:52,560 Och så jag kommer inte att kunna komma åt [1] [2]. 696 00:58:52,560 --> 00:58:58,370 Jag tror att det finns speciell syntax för att förklara en pekare, 697 00:58:58,370 --> 00:59:12,480 något löjligt som int (* p [-. något helt löjligt jag vet inte ens. 698 00:59:12,480 --> 00:59:17,090 Men det finns en syntax för att förklara pekare som med parenteser och saker. 699 00:59:17,090 --> 00:59:22,960 Det kanske inte ens låta dig göra det. 700 00:59:22,960 --> 00:59:26,640 Jag kunde se tillbaka på något som skulle berätta sanningen. 701 00:59:26,640 --> 00:59:34,160 Jag kommer att leta efter den senare, om det finns en syntax för punkt. Men du kommer aldrig att se det. 702 00:59:34,160 --> 00:59:39,670 Och även syntaxen är så ålderdomligt att om du använder det, kommer folk att förbryllad. 703 00:59:39,670 --> 00:59:43,540 Flerdimensionella arrayer är ganska sällsynt som det är. 704 00:59:43,540 --> 00:59:44,630 Du ganska mycket - 705 00:59:44,630 --> 00:59:48,490 Tja, om du gör matris saker som den inte kommer att vara sällsynta, 706 00:59:48,490 --> 00:59:56,730 men i C du sällan kommer att använda flerdimensionella arrayer. 707 00:59:57,630 --> 01:00:00,470 Ja. >> [Elev] Låt oss säga att du har en riktigt lång rad. 708 01:00:00,470 --> 01:00:03,900 >> Så i virtuellt minne verkar det vara alla på varandra följande, 709 01:00:03,900 --> 01:00:05,640 Liksom elementen intill varandra, 710 01:00:05,640 --> 01:00:08,770 men i det fysiska minnet, skulle det vara möjligt för den att delas upp? >> Ja. 711 01:00:08,770 --> 01:00:16,860 Hur virtuellt minne fungerar är det skiljer bara - 712 01:00:19,220 --> 01:00:24,860 Enheten för tilldelningen är en sida, som tenderar att vara 4 kilobyte, 713 01:00:24,860 --> 01:00:29,680 och så när en process säger hej, jag vill använda detta minne, 714 01:00:29,680 --> 01:00:35,970 operativsystemet kommer att fördela det 4 kilobyte för den lilla block av minne. 715 01:00:35,970 --> 01:00:39,100 Även om du bara använder en enda liten byte i hela block av minne, 716 01:00:39,100 --> 01:00:42,850 operativsystemet kommer att ge full 4 kilobyte. 717 01:00:42,850 --> 01:00:49,410 Så vad detta betyder är att jag kunde ha - låt oss säga att detta är min stack. 718 01:00:49,410 --> 01:00:53,180 Denna stapel kunde separeras. Min stack kan vara megabyte och megabyte. 719 01:00:53,180 --> 01:00:55,020 Min stack kan vara enorm. 720 01:00:55,020 --> 01:01:00,220 Men stapeln själv måste delas upp i enskilda sidor, 721 01:01:00,220 --> 01:01:09,010 som om vi tittar på här borta låt oss säga att detta är vår RAM, 722 01:01:09,010 --> 01:01:16,600 om jag har 2 gigabyte RAM-minne, är denna faktiska adress 0 som 0:e byte mitt RAM, 723 01:01:16,600 --> 01:01:22,210 och detta är 2 gigabyte hela vägen ner här. 724 01:01:22,210 --> 01:01:27,230 Så här sidan kan motsvara detta block hit. 725 01:01:27,230 --> 01:01:29,400 Denna sida kan motsvara detta block hit. 726 01:01:29,400 --> 01:01:31,560 Denna kan man motsvara detta en hit. 727 01:01:31,560 --> 01:01:35,540 Så operativsystemet är fri att tilldela fysiskt minne 728 01:01:35,540 --> 01:01:39,320 till en enskild sida godtyckligt. 729 01:01:39,320 --> 01:01:46,180 Och det betyder att om denna gräns råkar gränsla en matris, 730 01:01:46,180 --> 01:01:50,070 en matris råkar lämnas om detta och höger om denna ordning en sida, 731 01:01:50,070 --> 01:01:54,460 då matris kommer att delas upp i det fysiska minnet. 732 01:01:54,460 --> 01:01:59,280 Och sedan när du avslutar programmet, när processen avslutas, 733 01:01:59,280 --> 01:02:05,690 Dessa mappningar blir raderas och då är det gratis att använda dessa små block för andra saker. 734 01:02:14,730 --> 01:02:17,410 Fler frågor? 735 01:02:17,410 --> 01:02:19,960 [Elev] Pekaren aritmetik. >> Oh yeah. 736 01:02:19,960 --> 01:02:28,410 Strängar var lättare, men titta på något som Ints, 737 01:02:28,410 --> 01:02:35,000 så tillbaka till int x [4]; 738 01:02:35,000 --> 01:02:41,810 Huruvida detta är en matris eller om det är en pekare till en malloced rad 4 heltal, 739 01:02:41,810 --> 01:02:47,060 det kommer att behandlas på samma sätt. 740 01:02:50,590 --> 01:02:53,340 [Elev] Så arrayer är på högen? 741 01:03:01,400 --> 01:03:05,270 [Bowden] Arrayer är inte på högen. >> [Elev] Oh. 742 01:03:05,270 --> 01:03:08,320 >> [Bowden] Denna typ av matris tenderar att vara på stacken 743 01:03:08,320 --> 01:03:12,220 om du förklarade det på - ignorerar globala variabler. Använd inte globala variabler. 744 01:03:12,220 --> 01:03:16,280 Inne i en funktion jag säger int x [4]; 745 01:03:16,280 --> 01:03:22,520 Det kommer att skapa en 4-heltal blocket på stacken för denna array. 746 01:03:22,520 --> 01:03:26,960 Men denna malloc (4 * sizeof (int)); kommer att gå på högen. 747 01:03:26,960 --> 01:03:31,870 Men efter detta kan jag använda x och p i stort sett samma sätt, 748 01:03:31,870 --> 01:03:36,140 annat än de undantag jag sa tidigare om du kan tilldela sid. 749 01:03:36,140 --> 01:03:40,960 Tekniskt deras storlek är något annorlunda, men det är helt irrelevant. 750 01:03:40,960 --> 01:03:43,310 Du aldrig använda sina storlekar. 751 01:03:48,020 --> 01:03:56,810 P Jag skulle kunna säga p [3] = 2 eller x [3] = 2; 752 01:03:56,810 --> 01:03:59,680 Du kan använda dem i exakt samma sätt. 753 01:03:59,680 --> 01:04:01,570 Så pekare aritmetik nu - Ja. 754 01:04:01,570 --> 01:04:07,390 [Elev] behöver du inte göra p * om du har konsolerna? 755 01:04:07,390 --> 01:04:11,720 Konsolerna är en implicit dereference. >> Okej. 756 01:04:11,720 --> 01:04:20,200 Egentligen också vad du säger med kan du få flerdimensionella arrayer 757 01:04:20,200 --> 01:05:02,650 med pekare, vad du kan göra är något som, låt oss säga, int ** pp = malloc (sizeof (int *) * 5); 758 01:05:02,650 --> 01:05:06,900 Jag ska bara skriva ut allt först. 759 01:05:37,880 --> 01:05:41,020 Jag ville inte att en. 760 01:05:41,020 --> 01:05:42,550 Okej. 761 01:05:42,550 --> 01:05:48,910 Vad jag gjorde här är - Det borde vara pp [i]. 762 01:05:48,910 --> 01:05:53,680 Så pp är en pekare till en pekare. 763 01:05:53,680 --> 01:06:02,420 Du mallocing pp att peka på en rad av 5 int stjärnor. 764 01:06:02,420 --> 01:06:10,950 Så i minnet du har på stacken pp 765 01:06:10,950 --> 01:06:20,150 Det kommer att peka på en rad av 5 block som alla själva pekare. 766 01:06:20,150 --> 01:06:28,210 Och sen när jag malloc här nere, malloc jag att var och en av de enskilda pekare 767 01:06:28,210 --> 01:06:32,080 bör peka på en separat 4 byte på högen. 768 01:06:32,080 --> 01:06:35,870 Så detta pekar på 4 byte. 769 01:06:37,940 --> 01:06:40,660 Och den här pekar till en annan 4 byte. 770 01:06:40,660 --> 01:06:43,200 >> Och alla av dem pekar på sina egna 4 byte. 771 01:06:43,200 --> 01:06:49,080 Det ger mig ett sätt att göra flerdimensionella saker. 772 01:06:49,080 --> 01:06:58,030 Jag skulle kunna säga pp [3] [4], men nu detta är inte samma sak som flerdimensionella arrayer 773 01:06:58,030 --> 01:07:05,390 eftersom flerdimensionella arrayer det översatt [3] [4] till en enda förskjutning i x-array. 774 01:07:05,390 --> 01:07:14,790 Detta dereferences p, åtkomst den tredje indexet, då dereferences som 775 01:07:14,790 --> 01:07:20,790 och tillfarter - 4 skulle vara ogiltigt - det andra indexet. 776 01:07:24,770 --> 01:07:31,430 Medan när vi hade int x [3] [4] innan en flerdimensionell array 777 01:07:31,430 --> 01:07:35,740 och när du dubbelklickar fäste det är egentligen bara en enda dereference, 778 01:07:35,740 --> 01:07:40,490 du följer en enda pekare och sedan en förskjutning, 779 01:07:40,490 --> 01:07:42,850 Detta är verkligen 2D referenser. 780 01:07:42,850 --> 01:07:45,840 Du följer 2 separata pekare. 781 01:07:45,840 --> 01:07:50,420 Så detta också tekniskt kan du ha flerdimensionella arrayer 782 01:07:50,420 --> 01:07:53,550 där varje enskild grupp är olika storlekar. 783 01:07:53,550 --> 01:07:58,000 Så jag tror ojämna flerdimensionella arrayer är vad det kallas 784 01:07:58,000 --> 01:08:01,870 Sedan verkligen det första kan peka på något som har 10 element, 785 01:08:01,870 --> 01:08:05,540 den andra saken skulle kunna peka på något som har 100 element. 786 01:08:05,540 --> 01:08:10,790 [Elev] Finns det någon gräns för hur många tips du kan ha 787 01:08:10,790 --> 01:08:14,290 pekar på andra pekare? >> Nej 788 01:08:14,290 --> 01:08:17,010 Du kan ha int ***** sid. 789 01:08:18,050 --> 01:08:23,760 Tillbaka till pekare aritmetik - >> [elev] Oh. >> Ja. 790 01:08:23,760 --> 01:08:35,649 [Elev] Om jag har int *** p och sedan gör jag en dereferencing och jag säger p * är lika med detta värde, 791 01:08:35,649 --> 01:08:39,560 kommer det bara göra 1 nivå dereferencing? >> Ja. 792 01:08:39,560 --> 01:08:43,340 Så om jag vill komma åt det som det sista pekaren pekar på - 793 01:08:43,340 --> 01:08:46,210 Då du gör *** p. >> Okej. 794 01:08:46,210 --> 01:08:54,080 Så detta är p pekar på 1 block, pekar på ett annat block, pekar på ett annat block. 795 01:08:54,080 --> 01:09:02,010 Sen om du gör * p = något annat, då är du ändra detta 796 01:09:02,010 --> 01:09:13,640 att nu peka på ett annat block. >> Okej. 797 01:09:13,640 --> 01:09:17,649 >> [Bowden] Och om de skulle malloced, då du nu har läckt minne 798 01:09:17,649 --> 01:09:20,430 om du råkar ha olika referenser av dessa 799 01:09:20,430 --> 01:09:25,270 eftersom du inte kan gå tillbaka till de de som du bara kastade bort. 800 01:09:25,270 --> 01:09:29,550 Pointer aritmetik. 801 01:09:29,550 --> 01:09:36,310 int x [4], kommer att fördela en rad 4 heltal 802 01:09:36,310 --> 01:09:40,670 där x kommer att peka på början av arrayen. 803 01:09:40,670 --> 01:09:50,420 Så när jag säger något i stil med x [1], jag vill att det ska betyda gå till den andra heltal i arrayen, 804 01:09:50,420 --> 01:09:53,319 vilket skulle vara här. 805 01:09:53,319 --> 01:10:04,190 Men egentligen, det är 4 byte i arrayen eftersom heltal tar upp 4 bytes. 806 01:10:04,190 --> 01:10:08,470 Så en förskjutning av 1 betyder egentligen en förskjutning av 1 807 01:10:08,470 --> 01:10:12,030 gånger storlek oavsett vilken typ av arrayen är. 808 01:10:12,030 --> 01:10:17,170 Detta är en array av heltal, så det vet att göra 1 gånger storleken på int när den vill att kompensera. 809 01:10:17,170 --> 01:10:25,260 Den andra syntaxen. Kom ihåg att detta är ekvivalent med * (x + 1); 810 01:10:25,260 --> 01:10:35,250 När jag säger pekare + 1, vad att avkastningen är den adress som pekaren lagrar 811 01:10:35,250 --> 01:10:40,360 plus 1 gånger större typen av pekaren. 812 01:10:40,360 --> 01:10:59,510 Så om x = ox100, sedan x + 1 = ox104. 813 01:10:59,510 --> 01:11:19,750 Och du kan missbruka detta och säga något i stil char * c = (char *) x; 814 01:11:19,750 --> 01:11:23,050 och nu c kommer att vara samma adress som x. 815 01:11:23,050 --> 01:11:26,040 c kommer att vara lika med ox100, 816 01:11:26,040 --> 01:11:31,490 men c + 1 kommer att vara lika med ox101 817 01:11:31,490 --> 01:11:38,030 eftersom pekaren aritmetiska beror på vilken typ av pekare som du lägger till. 818 01:11:38,030 --> 01:11:45,390 Så c + 1, det ser på c, det är en röding pekare, så det kommer att lägga 1 gånger storleken på röding, 819 01:11:45,390 --> 01:11:48,110 som alltid kommer att vara 1, så du får 101, 820 01:11:48,110 --> 01:11:54,890 medan om jag gör x, vilket också är fortfarande 100, är ​​x + 1 kommer att vara 104. 821 01:11:56,660 --> 01:12:06,340 [Elev] Kan man använda C + + för att föra pekaren med 1? 822 01:12:06,340 --> 01:12:09,810 Ja, det kan du. 823 01:12:09,810 --> 01:12:16,180 Du kan inte göra det med X eftersom x är bara en symbol, det är en konstant, du kan inte ändra x. 824 01:12:16,180 --> 01:12:22,610 >> Men c råkar bara vara en pekare, så c + + är helt giltiga och det kommer öka med 1. 825 01:12:22,610 --> 01:12:32,440 Om c var bara en int *, då c + + skulle 104. 826 01:12:32,440 --> 01:12:41,250 + + Gör pekaren aritmetiska precis som C + 1 skulle ha gjort pekare aritmetik. 827 01:12:43,000 --> 01:12:48,870 Detta är faktiskt hur många saker som sammanslagning sort - 828 01:12:49,670 --> 01:12:55,710 Istället för att skapa kopior av saker, kan du skicka istället - 829 01:12:55,710 --> 01:13:02,400 Liksom om jag ville vidarebefordra detta halva arrayen - låt oss ta bort en del av detta. 830 01:13:04,770 --> 01:13:10,520 Låt oss säga att jag ville passera denna sida av matrisen till en funktion. 831 01:13:10,520 --> 01:13:12,700 Vad skulle jag gå till den funktionen? 832 01:13:12,700 --> 01:13:17,050 Om jag passerar X, jag passerar denna adress. 833 01:13:17,050 --> 01:13:23,780 Men jag vill passera denna viss adress. Så vad ska jag gå? 834 01:13:23,780 --> 01:13:26,590 [Studenten] Pointer + 2? 835 01:13:26,590 --> 01:13:29,350 [Bowden] Så x + 2. Ja. 836 01:13:29,350 --> 01:13:31,620 Det kommer att bli den här adressen. 837 01:13:31,620 --> 01:13:42,810 Du kommer också mycket ofta ser det som x [2] och sedan adressen för den. 838 01:13:42,810 --> 01:13:47,850 Så du måste ta adressen av det eftersom fästet är en implicit dereference. 839 01:13:47,850 --> 01:13:53,250 x [2] refererar till det värde som finns i den här rutan, och sedan vill adressen för den rutan, 840 01:13:53,250 --> 01:13:56,850 så du säger och x [2]. 841 01:13:56,850 --> 01:14:02,880 Så det är hur något i merge sort där du vill passera halv listan till något 842 01:14:02,880 --> 01:14:08,790 du verkligen bara passerar och x [2], och nu när det gäller den rekursiva anropet är berörda, 843 01:14:08,790 --> 01:14:12,510 min nya array börjar där. 844 01:14:12,510 --> 01:14:15,130 Sista minuten frågor. 845 01:14:15,130 --> 01:14:20,050 [Elev] Om vi ​​inte sätta ett et-tecken eller - vad är det som kallas? >> Star? 846 01:14:20,050 --> 01:14:23,200 [Elev] Star. >> Tekniskt dereference operatör, men - >> [elev] dereference. 847 01:14:23,200 --> 01:14:29,310 >> Om vi ​​inte sätter en stjärna eller ett et, vad händer om jag bara säga y = x och x är en pekare? 848 01:14:29,310 --> 01:14:34,620 Vilken typ av y? >> [Elev] Jag ska bara säga att det är pekare 2. 849 01:14:34,620 --> 01:14:38,270 Så om du bara säga y = x, nu x-och y pekar på samma sak. >> [Elev] Peka på samma sak. 850 01:14:38,270 --> 01:14:45,180 Och om x är en int pekare? >> Det skulle klaga eftersom du inte kan tilldela pekare. 851 01:14:45,180 --> 01:14:46,540 [Elev] Okej. 852 01:14:46,540 --> 01:14:51,860 Kom ihåg att pekare, även om vi drar dem som pilar, 853 01:14:51,860 --> 01:15:02,010 verkligen allt de lagrar - int * x - verkligen alla x lagrar är något som ox100, 854 01:15:02,010 --> 01:15:06,490 som vi råkar representera som pekar på blocket lagras vid 100. 855 01:15:06,490 --> 01:15:19,660 Så när jag säger int * y = x, jag bara kopiera ox100 till y, 856 01:15:19,660 --> 01:15:24,630 som vi bara kommer att representera som Y, även pekar på ox100. 857 01:15:24,630 --> 01:15:39,810 Och om jag säger int i = (int) x; då jag kommer att lagra oavsett värdet på ox100 är 858 01:15:39,810 --> 01:15:45,100 inuti den, men nu det kommer att tolkas som ett heltal i stället för en pekare. 859 01:15:45,100 --> 01:15:49,310 Men du behöver gjutna annars kommer det att klaga. 860 01:15:49,310 --> 01:15:53,300 [Elev] Så menar du att kasta - 861 01:15:53,300 --> 01:16:00,290 Kommer det att vara gjutning int av x eller gjutning int y? 862 01:16:00,290 --> 01:16:03,700 [Bowden] Vad? 863 01:16:03,700 --> 01:16:07,690 [Elev] Okej. Efter dessa parenteser finns det kommer att bli ett x eller ay där? 864 01:16:07,690 --> 01:16:11,500 >> [Bowden] Antingen. x och y är likvärdiga. >> [Elev] Okej. 865 01:16:11,500 --> 01:16:14,390 Eftersom de är båda pekare. >> Ja. 866 01:16:14,390 --> 01:16:21,050 [Elev] Så det skulle lagra hexadecimala 100 i heltal form? >> [Bowden] Ja. 867 01:16:21,050 --> 01:16:23,620 Men inte värdet av vad det pekar på. 868 01:16:23,620 --> 01:16:29,940 [Bowden] Ja. >> [Elev] Så bara adressen i heltal form. Okej. 869 01:16:29,940 --> 01:16:34,720 [Bowden] Om du ville av någon bisarr anledning, 870 01:16:34,720 --> 01:16:38,900 du kan endast hantera pekare och aldrig ta itu med heltal 871 01:16:38,900 --> 01:16:49,240 och bara vara som int * x = 0. 872 01:16:49,240 --> 01:16:53,000 Då du kommer att bli riktigt förvirrad när pekaren aritmetiska börjar hända. 873 01:16:53,000 --> 01:16:56,570 Så de nummer som de lagrar är meningslösa. 874 01:16:56,570 --> 01:16:58,940 Det är bara hur du hamna tolka dem. 875 01:16:58,940 --> 01:17:02,920 Så jag är fri att kopiera ox100 från en int * till en int, 876 01:17:02,920 --> 01:17:07,790 och jag är fri att tilldela - Du är förmodligen kommer att få yelled på för att inte kasta - 877 01:17:07,790 --> 01:17:18,160 Jag är fri att tilldela något liknande (int *) ox1234 i denna godtyckliga int *. 878 01:17:18,160 --> 01:17:25,480 Så ox123 är lika giltiga en minnesadress som är & Y. 879 01:17:25,480 --> 01:17:32,060 & Y råkar återvända något som är ganska mycket ox123. 880 01:17:32,060 --> 01:17:35,430 [Eleven] Skulle det vara en riktigt cool sätt att gå från hexadecimalt till decimalform, 881 01:17:35,430 --> 01:17:39,230 som om du har en pekare och du kastar den som en int? 882 01:17:39,230 --> 01:17:44,860 [Bowden] Du kan egentligen bara ut med som printf. 883 01:17:44,860 --> 01:17:50,300 Låt oss säga att jag har int y = 100. 884 01:17:50,300 --> 01:18:02,700 Så printf (% d \ n - som ni redan borde veta - skriv ut det som ett heltal,% x. 885 01:18:02,700 --> 01:18:05,190 Vi ska bara skriva ut det som hexadecimalt. 886 01:18:05,190 --> 01:18:10,760 Så en pekare inte lagras som hexadecimalt, 887 01:18:10,760 --> 01:18:12,960 och ett heltal inte lagras som decimaltal. 888 01:18:12,960 --> 01:18:14,700 Allt lagras som binära. 889 01:18:14,700 --> 01:18:17,950 Det är bara det att vi tenderar att visa pekare som hexadecimala 890 01:18:17,950 --> 01:18:23,260 eftersom vi tror på saker i dessa 4-byte block, 891 01:18:23,260 --> 01:18:25,390 och minnesadresser tenderar att vara bekant. 892 01:18:25,390 --> 01:18:28,890 Vi är som, om den börjar med bf, då det råkar vara på stacken. 893 01:18:28,890 --> 01:18:35,560 Så det är bara vår tolkning av pekare som hexadecimalt. 894 01:18:35,560 --> 01:18:39,200 Okej. Några sista frågor? 895 01:18:39,200 --> 01:18:41,700 >> Jag kommer att vara här ett tag efter om du har något annat. 896 01:18:41,700 --> 01:18:46,070 Och det är slutet av den. 897 01:18:46,070 --> 01:18:48,360 >> [Elev] Yay! [Applåder] 898 01:18:51,440 --> 01:18:53,000 >> [CS50.TV]