1 00:00:00,000 --> 00:00:02,520 [Powered by Google Translate] [Sekcja 4 - bardziej komfortowe] 2 00:00:02,520 --> 00:00:04,850 [Rob Bowden - Harvard University] 3 00:00:04,850 --> 00:00:07,370 [To jest CS50. - CS50.TV] 4 00:00:08,920 --> 00:00:13,350 Mamy jutro test, w przypadku wy nie wiedziałem. 5 00:00:14,810 --> 00:00:20,970 Jest to w zasadzie na wszystko, co widzieliście w klasie lub powinien zobaczyć w klasie. 6 00:00:20,970 --> 00:00:26,360 , Który zawiera wskaźniki, chociaż jest to bardzo niedawno temat. 7 00:00:26,360 --> 00:00:29,860 Należy przynajmniej zrozumieć wysoki poziom nich. 8 00:00:29,860 --> 00:00:34,760 Wszystko, co nie było na klasy należy zrozumieć na quiz. 9 00:00:34,760 --> 00:00:37,320 Tak więc, jeśli masz pytania na ich temat, możesz zadać je teraz. 10 00:00:37,320 --> 00:00:43,280 Ale to będzie bardzo student-led sesja gdzie wam zadawać pytania, 11 00:00:43,280 --> 00:00:45,060 więc mam nadzieję, że ludzie mają pytania. 12 00:00:45,060 --> 00:00:48,020 Czy ktoś ma pytania? 13 00:00:49,770 --> 00:00:52,090 Tak. >> [Uczeń] można przejść wskaźniki ponownie? 14 00:00:52,090 --> 00:00:54,350 Pójdę na wskaźniki. 15 00:00:54,350 --> 00:00:59,180 Wszystkich swoich zmiennych muszą żyć w pamięci, 16 00:00:59,180 --> 00:01:04,450 ale zazwyczaj nie martw się o tym i po prostu powiedzieć, x + 2 i y + 3 17 00:01:04,450 --> 00:01:07,080 i kompilator będzie dowiedzieć się, gdzie te rzeczy żyją dla Ciebie. 18 00:01:07,080 --> 00:01:12,990 Gdy masz do czynienia z wskaźników, teraz jesteś jawnie przy użyciu tych adresów pamięci. 19 00:01:12,990 --> 00:01:19,800 Tak więc pojedyncza zmienna będzie zawsze tylko żyć pod jednym adresem w danej chwili. 20 00:01:19,800 --> 00:01:24,040 Jeśli chcemy zadeklarować wskaźnik, co jest typ będzie wyglądać? 21 00:01:24,040 --> 00:01:26,210 >> Chcę zadeklarować p wskaźnika. Co typ wygląda? 22 00:01:26,210 --> 00:01:33,530 [Uczeń] int * p. >> Tak. Więc int * p. 23 00:01:33,530 --> 00:01:38,030 A jak zrobić, żeby ją wskazać x? >> [Uczeń] Ampersand. 24 00:01:40,540 --> 00:01:45,300 [Bowden] Więc ampersand dosłownie nazywane adres operatora. 25 00:01:45,300 --> 00:01:50,460 Więc kiedy mówię & x robi się adres pamięci zmiennej x. 26 00:01:50,460 --> 00:01:56,790 Więc teraz mam t wskaźnik, i nigdzie w moim kodu można używać * P 27 00:01:56,790 --> 00:02:02,960 czy mogę używać X i będzie to dokładnie to samo. 28 00:02:02,960 --> 00:02:09,520 (* P). Co to robi? Co oznacza, że ​​gwiazdka oznacza? 29 00:02:09,520 --> 00:02:13,120 [Uczeń] To oznacza wartość w tym punkcie. >> Tak. 30 00:02:13,120 --> 00:02:17,590 Więc jeśli spojrzymy na to, to może być bardzo przydatne, aby wyciągnąć schematy 31 00:02:17,590 --> 00:02:22,230 tam gdzie jest to małe pudełko pamięci dla x, co zdarza się mieć wartość 4, 32 00:02:22,230 --> 00:02:25,980 wtedy mamy małe okienko pamięci dla P, 33 00:02:25,980 --> 00:02:31,590 i tak punktów p. X, więc narysować strzałkę od P do x. 34 00:02:31,590 --> 00:02:40,270 Więc, gdy mówimy, p * mówimy przejść do pola, które jest p. 35 00:02:40,270 --> 00:02:46,480 Star jest śledzić strzałkę i robić, co chcesz z tym polu tam. 36 00:02:46,480 --> 00:03:01,090 Więc mogę powiedzieć, * p = 7, i że trafi do pudełka, które jest x, a zmiany, które do 7. 37 00:03:01,090 --> 00:03:13,540 Albo można powiedzieć int z = * p * 2; To się myli, bo to gwiazda, gwiazda. 38 00:03:13,540 --> 00:03:19,230 Jedna gwiazda jest dereferencji t, druga gwiazda jest pomnożenie przez 2. 39 00:03:19,230 --> 00:03:26,780 Zauważ, mógłbym równie dobrze zastąpiła P * z x. 40 00:03:26,780 --> 00:03:29,430 Można ich używać w taki sam sposób. 41 00:03:29,430 --> 00:03:38,000 A później na I może mieć punkt P do zupełnie nowej rzeczy. 42 00:03:38,000 --> 00:03:42,190 Mogę tylko powiedzieć, p = &z; 43 00:03:42,190 --> 00:03:44,940 Więc teraz P nie wskazuje już na X, to wskazuje na z. 44 00:03:44,940 --> 00:03:50,510 I za każdym razem zrobić P * to jest to samo, jak robi z.. 45 00:03:50,510 --> 00:03:56,170 Więc przydatna rzeczą jest to, kiedy już zaczną się do funkcji. 46 00:03:56,170 --> 00:03:59,790 >> To trochę bezużyteczne zadeklarować wskaźnik, który wskazuje na coś 47 00:03:59,790 --> 00:04:03,140 a potem po prostu go dereferencji 48 00:04:03,140 --> 00:04:06,060 kiedy może użyłeś oryginalnej zmiennej na początku. 49 00:04:06,060 --> 00:04:18,190 Ale kiedy się do funkcji - tak powiedzmy mamy kilka funkcji, int foo 50 00:04:18,190 --> 00:04:32,810 która pobiera wskaźnik i po prostu robi * p = 6; 51 00:04:32,810 --> 00:04:39,990 Jak widzieliśmy wcześniej z wymiany, nie można zrobić skuteczną swapa i oddzielną funkcję 52 00:04:39,990 --> 00:04:45,180 by tylko przejazdem liczby całkowite, ponieważ wszystko w C zawsze przechodzi przez wartość. 53 00:04:45,180 --> 00:04:48,360 Nawet jeśli jesteś przejazdem wskaźniki jesteś przejazdem przez wartość. 54 00:04:48,360 --> 00:04:51,940 Tak się składa, że ​​te wartości są adresy pamięci. 55 00:04:51,940 --> 00:05:00,770 Więc kiedy mówię foo (p); olewam wskaźnik do funkcji foo 56 00:05:00,770 --> 00:05:03,910 a następnie foo robi * p = 6; 57 00:05:03,910 --> 00:05:08,600 Tak więc w środku tej funkcji, * p nadal odpowiada X 58 00:05:08,600 --> 00:05:12,720 , ale nie można używać X wewnątrz tej funkcji, ponieważ nie jest objęty zakresem wewnątrz tej funkcji. 59 00:05:12,720 --> 00:05:19,510 Więc * p = 6 jest to jedyny sposób można uzyskać dostęp do lokalnej zmiennej z innej funkcji. 60 00:05:19,510 --> 00:05:23,600 Albo dobrze, wskaźniki są jedynym sposobem, można uzyskać dostęp do lokalnej zmiennej z innej funkcji. 61 00:05:23,600 --> 00:05:31,600 [Uczeń] Powiedzmy, że chciał wrócić wskaźnik. Jak dokładnie to zrobić? 62 00:05:31,600 --> 00:05:44,270 [Bowden] zwraca wskaźnik jak w coś int y = 3; return & y? >> [Uczeń] Tak. 63 00:05:44,270 --> 00:05:48,480 [Bowden] Dobra. Nigdy nie należy tego robić. To jest złe. 64 00:05:48,480 --> 00:05:59,480 Myślę, że widziałem w tych slajdach wykładów początek widząc ten cały schemat pamięci 65 00:05:59,480 --> 00:06:02,880 gdzie tu masz adres pamięci 0 66 00:06:02,880 --> 00:06:09,550 a tu masz adres w pamięci 4 koncertów lub 2 do 32. 67 00:06:09,550 --> 00:06:15,120 Więc masz trochę rzeczy i pewne rzeczy, a potem masz stos 68 00:06:15,120 --> 00:06:21,780 i masz swoją kupę, która właśnie rozpoczęła naukę o, dorastanie. 69 00:06:21,780 --> 00:06:24,390 [Uczeń] nie kupie powyżej stosu? 70 00:06:24,390 --> 00:06:27,760 >> Tak. Kupa jest na górze, prawda? >> [Uczeń] Cóż, położył 0 na górze. 71 00:06:27,760 --> 00:06:30,320 [Uczeń] Oh, położył 0 na górze. >> [Uczeń] Oh, w porządku. 72 00:06:30,320 --> 00:06:36,060 Zastrzeżenie: Anywhere z CS50 masz zamiar zobaczyć to w ten sposób. >> [Uczeń] Dobra. 73 00:06:36,060 --> 00:06:40,290 Tyle, że kiedy jesteś 1-ci widząc stosy, 74 00:06:40,290 --> 00:06:45,000 jak wtedy, gdy uważasz, że stos myśleć układanie rzeczy na jeden na drugim. 75 00:06:45,000 --> 00:06:50,810 Więc staramy się przerzucić to około tak stos rośnie jak stos normalnie 76 00:06:50,810 --> 00:06:55,940 zamiast stosu zwisa. >> [Uczeń] nie hałdy technicznie dorastają zbyt, chociaż? 77 00:06:55,940 --> 00:07:01,100 To zależy co masz na myśli przez dorosnąć. 78 00:07:01,100 --> 00:07:04,010 Stosu i sterty zawsze rosną w przeciwnych kierunkach. 79 00:07:04,010 --> 00:07:09,420 Stos jest zawsze dorastanie w tym sensie, że dorasta 80 00:07:09,420 --> 00:07:12,940 w kierunku wyższych adresów pamięci i sterty rośnie w dół 81 00:07:12,940 --> 00:07:17,260 w tym, że w kierunku niższych rośnie adresów pamięci. 82 00:07:17,260 --> 00:07:20,250 Najlepiej jest więc 0 i dolny adresy pamięci jest wysokie. 83 00:07:20,250 --> 00:07:26,390 Oboje rośnie, tylko w przeciwnych kierunkach. 84 00:07:26,390 --> 00:07:29,230 [Uczeń] Chodziło mi o to, że ponieważ pan powiedział umieścić stos na dnie 85 00:07:29,230 --> 00:07:33,640 , ponieważ wydaje się, ze względu na bardziej intuicyjne stosu zacząć od góry stos, 86 00:07:33,640 --> 00:07:37,520 kupa jest na górze sobie też, więc that's - >> Tak. 87 00:07:37,520 --> 00:07:44,960 Również pomyśleć o stercie jak dorasta i większe, ale stos bardziej. 88 00:07:44,960 --> 00:07:50,280 Więc stos jest jeden, że niby chcą pokazać dorastanie. 89 00:07:50,280 --> 00:07:55,390 Ale wszędzie wyglądasz inaczej pokaże adres 0 na górze 90 00:07:55,390 --> 00:07:59,590 a najwyższy adres pamięci na dole, więc jest to zwykły widok z pamięci. 91 00:07:59,590 --> 00:08:02,100 >> Czy masz pytanie? 92 00:08:02,100 --> 00:08:04,270 [Student] Czy możesz nam powiedzieć więcej o stercie? 93 00:08:04,270 --> 00:08:06,180 Tak. I ci się, że w drugim. 94 00:08:06,180 --> 00:08:12,220 Po pierwsze, dlaczego wraca do powrotu & Y jest złe, 95 00:08:12,220 --> 00:08:18,470 na stosie masz kilka ramek stosu, które reprezentują wszystkie funkcje 96 00:08:18,470 --> 00:08:20,460 które nazywane. 97 00:08:20,460 --> 00:08:27,990 Więc ignorując wcześniejsze rzeczy, w górnej części stosu jest zawsze będzie głównym zadaniem 98 00:08:27,990 --> 00:08:33,090 ponieważ jest to pierwsza funkcja, która jest wezwaniem. 99 00:08:33,090 --> 00:08:37,130 A potem, kiedy wywołać inną funkcję, stos ma rosnąć w dół. 100 00:08:37,130 --> 00:08:41,640 Więc jeśli zgłoszę niektórych funkcji, Foo, i robi własne ramki stosu, 101 00:08:41,640 --> 00:08:47,280 może wywołać jakąś funkcję, bar; robi własne ramki stosu. 102 00:08:47,280 --> 00:08:49,840 I bar może być rekurencyjna i może wywoła się 103 00:08:49,840 --> 00:08:54,150 i tak, że drugie zaproszenie do baru dostanie swoją ramkę stosu. 104 00:08:54,150 --> 00:08:58,880 A więc to, co dzieje się w tych ramkach stosu są wszystkie zmienne lokalne 105 00:08:58,880 --> 00:09:03,450 i wszystkie argumenty funkcji, która - 106 00:09:03,450 --> 00:09:08,730 Wszelkie rzeczy, które są lokalnie zawężona do tej funkcji przejść w tych ramek stosu. 107 00:09:08,730 --> 00:09:21,520 To znaczy, że kiedy powiedział coś jak bar jest funkcją, 108 00:09:21,520 --> 00:09:29,270 Idę tylko do deklarowania liczby całkowitej, a następnie zwraca wskaźnik do tego całkowitej. 109 00:09:29,270 --> 00:09:33,790 Więc skąd y mieszka? 110 00:09:33,790 --> 00:09:36,900 [Uczeń] y mieszka w barze. >> [Bowden] Tak. 111 00:09:36,900 --> 00:09:45,010 Gdzieś w tym małym placu w pamięci to, że ma kwadratowy Littler y w nim. 112 00:09:45,010 --> 00:09:53,370 Kiedy wrócę & y, jestem zwracając wskaźnik do tego małego bloku pamięci. 113 00:09:53,370 --> 00:09:58,400 Ale wtedy, gdy a funkcja zwraca jego ramki stosu pobiera zdejmowana stos. 114 00:10:01,050 --> 00:10:03,530 I dlatego nazywa się to stosu. 115 00:10:03,530 --> 00:10:06,570 To jak struktury danych stosu, jeśli wiesz, co to jest. 116 00:10:06,570 --> 00:10:11,580 Albo nawet jak stos tac jest zawsze przykładem, 117 00:10:11,580 --> 00:10:16,060 Głównym będzie iść na dno, to pierwsza funkcja zadzwonić będzie przejść na początku, że 118 00:10:16,060 --> 00:10:20,400 i nie możesz wrócić do głównego, aż wrócisz z wszystkich funkcji, które zostały nazwane 119 00:10:20,400 --> 00:10:22,340 , które zostały umieszczone na nim. 120 00:10:22,340 --> 00:10:28,650 >> [Uczeń] Więc jeśli zrobił zwrot & Y, że wartość jest ulec zmianie bez powiadomienia. 121 00:10:28,650 --> 00:10:31,290 Tak, it's - >> [uczeń] To może być zastąpiony. >> Tak. 122 00:10:31,290 --> 00:10:34,660 Jest całkowicie - Jeśli spróbujesz - 123 00:10:34,660 --> 00:10:38,040 Byłoby to również int bar * bo to zwracając wskaźnik, 124 00:10:38,040 --> 00:10:41,310 więc jego powrót jest typ int *. 125 00:10:41,310 --> 00:10:46,500 Jeśli spróbujesz użyć zwracanej wartości tej funkcji, jest niezdefiniowane zachowanie 126 00:10:46,500 --> 00:10:51,770 dlatego, że wskaźnik wskazuje na złą pamięć. >> [Uczeń] Dobra. 127 00:10:51,770 --> 00:11:01,250 Więc co, jeśli, na przykład, oświadczył int * y = malloc (sizeof (int))? 128 00:11:01,250 --> 00:11:03,740 To jest lepsze. Tak. 129 00:11:03,740 --> 00:11:07,730 [Uczeń] Rozmawialiśmy o tym, jak, kiedy przeciągnąć rzeczy do naszego kosza 130 00:11:07,730 --> 00:11:11,750 nie są one rzeczywiście skasowane, po prostu tracą swoje wskaźniki. 131 00:11:11,750 --> 00:11:15,550 Więc w tym przypadku mamy faktycznie usunąć wartość, czy jest to nadal istnieje w pamięci? 132 00:11:15,550 --> 00:11:19,130 W przeważającej części, to będzie nadal istnieje. 133 00:11:19,130 --> 00:11:24,220 Ale powiedzmy, że zdarzy nam się wywołać jakąś inną funkcję, baz. 134 00:11:24,220 --> 00:11:28,990 Baz dostanie swoją ramkę stosu tutaj. 135 00:11:28,990 --> 00:11:31,470 To będzie nadpisywania wszystkich tych rzeczy, 136 00:11:31,470 --> 00:11:34,180 a jeśli później spróbować skorzystać wskaźnik, że masz przed, 137 00:11:34,180 --> 00:11:35,570 to nie będzie ta sama wartość. 138 00:11:35,570 --> 00:11:38,150 To się zmieniło tylko dlatego, że nazywa się BAZ funkcji. 139 00:11:38,150 --> 00:11:43,080 [Uczeń] Ale gdyby nie my, będziemy nadal się 3? 140 00:11:43,080 --> 00:11:44,990 [Bowden] Według wszelkiego prawdopodobieństwa, że ​​tak. 141 00:11:44,990 --> 00:11:49,670 Ale nie można powoływać się na to. C po prostu mówi niezdefiniowane zachowanie. 142 00:11:49,670 --> 00:11:51,920 >> [Uczeń] Oh, to nie. Okay. 143 00:11:51,920 --> 00:11:58,190 Więc gdy chcesz powrócić wskaźnik, to jest, gdy malloc jest w użyciu. 144 00:12:00,930 --> 00:12:15,960 Piszę właściwie tylko powrócić malloc (3 * sizeof (int)). 145 00:12:17,360 --> 00:12:24,050 Pójdziemy na malloc więcej w drugim, ale idea jest malloc wszystkich zmiennych lokalnych 146 00:12:24,050 --> 00:12:26,760 zawsze idą na stos. 147 00:12:26,760 --> 00:12:31,570 Wszystko, co jest malloced idzie na stercie, i będzie na zawsze i być zawsze na stercie 148 00:12:31,570 --> 00:12:34,490 dopóki jawnie zwolnić go. 149 00:12:34,490 --> 00:12:42,130 Więc to oznacza, że ​​gdy malloc coś, to będzie przeżyć po powrocie funkcji. 150 00:12:42,130 --> 00:12:46,800 [Student] Czy przetrwa po program zatrzyma? No >> 151 00:12:46,800 --> 00:12:53,180 Okay, więc to będzie tam, aż program wszystko jest sposób zrobić uruchomiony. >> Tak. 152 00:12:53,180 --> 00:12:57,510 Możemy iść na szczegóły tego, co się dzieje, gdy program przestanie działać. 153 00:12:57,510 --> 00:13:02,150 Być może trzeba mi przypominać, ale to osobna sprawa całkowicie. 154 00:13:02,150 --> 00:13:04,190 [Uczeń] Więc malloc tworzy wskaźnik? >> Tak. 155 00:13:04,190 --> 00:13:13,030 Malloc - >> [uczeń] Myślę malloc oznacza blok pamięci, że wskaźnik może wykorzystać. 156 00:13:15,400 --> 00:13:19,610 [Bowden] Chcę, aby ten schemat ponownie. >> [Uczeń] Więc ta funkcja działa, chociaż? 157 00:13:19,610 --> 00:13:26,430 [Uczeń] Tak, malloc oznacza blok pamięci, których można używać, 158 00:13:26,430 --> 00:13:30,470 , a następnie powraca na adres pierwszego bloku tej pamięci. 159 00:13:30,470 --> 00:13:36,750 >> [Bowden] Tak. Więc gdy malloc, jesteś chwytając jakiś blok pamięci 160 00:13:36,750 --> 00:13:38,260 to jest obecnie w stercie. 161 00:13:38,260 --> 00:13:43,040 Jeżeli stos jest zbyt mała, a następnie po prostu sterty rosnąć i rośnie w tym kierunku. 162 00:13:43,040 --> 00:13:44,650 Powiedzmy więc, że kupa jest zbyt mała. 163 00:13:44,650 --> 00:13:49,960 Wtedy to właśnie rosną trochę i zwraca wskaźnik do tego bloku, które po prostu rósł. 164 00:13:49,960 --> 00:13:55,130 Po darmowe rzeczy, robisz więcej miejsca w kupie, 165 00:13:55,130 --> 00:14:00,030 tak to później zadzwonić do malloc może ponownie tej pamięci, które były wcześniej zwolnione. 166 00:14:00,030 --> 00:14:09,950 Ważną rzeczą malloc i free jest to, że daje pełną kontrolę 167 00:14:09,950 --> 00:14:12,700 w okresie eksploatacji tych bloków pamięci. 168 00:14:12,700 --> 00:14:15,420 Zmienne globalne są zawsze żywe. 169 00:14:15,420 --> 00:14:18,500 Zmienne lokalne są żywe w ich zakres. 170 00:14:18,500 --> 00:14:22,140 Tak szybko, jak przejść obok klamra kręcone, zmienne lokalne są martwe. 171 00:14:22,140 --> 00:14:28,890 Malloced pamięć jest żywa, gdy chcesz, aby żyć 172 00:14:28,890 --> 00:14:33,480 a następnie jest uwalniany, gdy powiesz to do wydania. 173 00:14:33,480 --> 00:14:38,420 Są to faktycznie tylko 3 rodzaje pamięci, naprawdę. 174 00:14:38,420 --> 00:14:41,840 Jest automatyczne zarządzanie pamięcią, który jest stos. 175 00:14:41,840 --> 00:14:43,840 Wszystko dzieje się automatycznie. 176 00:14:43,840 --> 00:14:46,910 Kiedy mówisz, int x, pamięć została przydzielona do int x. 177 00:14:46,910 --> 00:14:51,630 Gdy x wychodzi z zakresu, pamięć jest przeznaczane do x. 178 00:14:51,630 --> 00:14:54,790 Potem jest dynamiczne zarządzanie pamięcią, która jest, co malloc jest 179 00:14:54,790 --> 00:14:56,740 co jest, gdy masz kontrolę. 180 00:14:56,740 --> 00:15:01,290 Ty decydujesz, kiedy dynamicznie pamięć powinna i nie powinna być przypisana. 181 00:15:01,290 --> 00:15:05,050 A wtedy nie statyczne, co oznacza po prostu, że żyje wiecznie, 182 00:15:05,050 --> 00:15:06,610 czyli to, co zmienne globalne są. 183 00:15:06,610 --> 00:15:10,240 Oni po prostu zawsze w pamięci. 184 00:15:10,960 --> 00:15:12,760 >> Pytania? 185 00:15:14,490 --> 00:15:17,230 [Student] Czy możesz zdefiniować blok tylko za pomocą nawiasów klamrowych 186 00:15:17,230 --> 00:15:21,220 ale nie trzeba mieć, jeśli oświadczenia lub while lub coś podobnego? 187 00:15:21,220 --> 00:15:29,130 Można zdefiniować blok, jak w funkcji, ale ma nawiasy klamrowe też. 188 00:15:29,130 --> 00:15:32,100 [Uczeń] Więc nie możesz po prostu mieć jak losowej nawiasach klamrowych w kodzie 189 00:15:32,100 --> 00:15:35,680 które mają zmienne lokalne? >> Tak, można. 190 00:15:35,680 --> 00:15:45,900 Wewnątrz int barze mogliśmy {int y = 3;}. 191 00:15:45,900 --> 00:15:48,440 To ma być właśnie tutaj. 192 00:15:48,440 --> 00:15:52,450 Ale to całkowicie definiuje zakres int y. 193 00:15:52,450 --> 00:15:57,320 Po tym drugim nawiasem klamrowym, y nie może być już używany. 194 00:15:57,910 --> 00:16:00,630 Ty prawie nigdy nie zrobić, choć. 195 00:16:02,940 --> 00:16:07,370 Wracając do tego, co się dzieje, gdy program się kończy, 196 00:16:07,370 --> 00:16:18,760 tam trochę nieporozumienie / pół kłamstwo, że dajemy, aby po prostu zrobić łatwiej. 197 00:16:18,760 --> 00:16:24,410 Mówimy wam, że kiedy przydzielić pamięci 198 00:16:24,410 --> 00:16:29,860 jesteś przydzielania którąś pamięci RAM dla tej zmiennej. 199 00:16:29,860 --> 00:16:34,190 Ale ty nie jesteś naprawdę bezpośrednio dotykając RAM nigdy w swoich programach. 200 00:16:34,190 --> 00:16:37,490 Jeśli myślisz o tym, jak zwróciłem - 201 00:16:37,490 --> 00:16:44,330 I rzeczywiście, jeśli przejdziesz przez w GDB zobaczysz to samo. 202 00:16:51,120 --> 00:16:57,590 Niezależnie od tego, ile razy można uruchomić program lub jakiego programu używasz, 203 00:16:57,590 --> 00:16:59,950 stosu zawsze będzie start - 204 00:16:59,950 --> 00:17:06,510 zawsze masz zamiar zobaczyć zmiennych wokół czegoś oxbffff adresowej. 205 00:17:06,510 --> 00:17:09,470 To zazwyczaj gdzieś w tym regionie. 206 00:17:09,470 --> 00:17:18,760 Ale jak 2 programy ewentualnie mieć wskaźniki do tej samej pamięci? 207 00:17:20,640 --> 00:17:27,650 [Uczeń] Jest trochę arbitralne wyznaczenie gdzie oxbfff ma być w pamięci RAM 208 00:17:27,650 --> 00:17:31,320 że w rzeczywistości może być w różnych miejscach, w zależności od, gdy funkcja została wywołana. 209 00:17:31,320 --> 00:17:35,920 Tak. Termin jest pamięć wirtualna. 210 00:17:35,920 --> 00:17:42,250 Chodzi o to, że każdy proces, każdy program uruchomiony na komputerze 211 00:17:42,250 --> 00:17:49,450 ma swój własny - załóżmy 32 bitów - całkowicie niezależne przestrzeni adresowej. 212 00:17:49,450 --> 00:17:51,590 Jest to przestrzeń adresowa. 213 00:17:51,590 --> 00:17:56,220 Ma własne całkowicie niezależne 4 GB do wykorzystania. 214 00:17:56,220 --> 00:18:02,220 >> Więc jeśli uruchomić 2 programów jednocześnie, program ten widzi 4 GB do siebie, 215 00:18:02,220 --> 00:18:04,870 program ten widzi 4 GB do siebie, 216 00:18:04,870 --> 00:18:07,720 i nie da się do tego programu do nieprawidłowego wskaźnika 217 00:18:07,720 --> 00:18:10,920 i kończy się z pamięci z tego programu. 218 00:18:10,920 --> 00:18:18,200 A co z pamięci wirtualnej jest odwzorowanie z przestrzeni adresowej procesów 219 00:18:18,200 --> 00:18:20,470 do rzeczywistych rzeczy na RAM. 220 00:18:20,470 --> 00:18:22,940 Więc to zależy od systemu operacyjnego, aby wiedzieć, że 221 00:18:22,940 --> 00:18:28,080 hej, kiedy ten facet wskaźnik dereferences oxbfff, że naprawdę oznacza 222 00:18:28,080 --> 00:18:31,040 że chce RAM bajt 1000, 223 00:18:31,040 --> 00:18:38,150 natomiast jeśli to oxbfff dereferences program, naprawdę chce RAM bajt 10000. 224 00:18:38,150 --> 00:18:41,590 Mogą być dowolnie daleko od siebie. 225 00:18:41,590 --> 00:18:48,730 Jest to prawdziwe nawet w rzeczy jednej przestrzeni adresowej procesów. 226 00:18:48,730 --> 00:18:54,770 Tak jak to widzi wszystkie 4 gigabajtów do siebie, ale powiedzmy - 227 00:18:54,770 --> 00:18:57,290 [Student] Czy każdy proces - 228 00:18:57,290 --> 00:19:01,350 Powiedzmy, że masz komputer z tylko 4 GB pamięci RAM. 229 00:19:01,350 --> 00:19:06,430 Czy każdy pojedynczy proces zobaczyć całe 4 GB? >> Tak. 230 00:19:06,430 --> 00:19:13,060 Ale 4 gigabajty to widzi, to kłamstwo. 231 00:19:13,060 --> 00:19:20,460 To jest po prostu myśli, że to wszystko ma pamięć, bo nie wiem, żadna inna metoda nie istnieje. 232 00:19:20,460 --> 00:19:28,140 Będzie używać tylko tyle pamięci, jak to faktycznie potrzebuje. 233 00:19:28,140 --> 00:19:32,340 System operacyjny nie da się tego procesu RAM 234 00:19:32,340 --> 00:19:35,750 Jeżeli to nie jest przy tym w żadnej pamięci całego regionu. 235 00:19:35,750 --> 00:19:39,300 To się nie dać mu w pamięć dla tego regionu. 236 00:19:39,300 --> 00:19:54,780 Ale idea jest taka, że ​​- Staram się myśleć o - Nie mogę myśleć o analogii. 237 00:19:54,780 --> 00:19:56,780 Analogie są trudne. 238 00:19:57,740 --> 00:20:02,700 Jednym z problemów, pamięci wirtualnej lub jedna z rzeczy, to jest rozwiązywanie 239 00:20:02,700 --> 00:20:06,810 jest to, że proces powinien być całkowicie nieświadomy siebie. 240 00:20:06,810 --> 00:20:12,140 I tak można napisać dowolny program, że tylko dereferences żadnego wskaźnika, 241 00:20:12,140 --> 00:20:19,340 jak tylko napisać program, który mówi * (ox1234) 242 00:20:19,340 --> 00:20:22,890 i to dereferencji adres pamięci 1234. 243 00:20:22,890 --> 00:20:28,870 >> Ale to zależy od systemu operacyjnego, aby następnie w tłumaczeniu, co 1234 znaczy. 244 00:20:28,870 --> 00:20:33,960 Więc jeśli 1234 dzieje się, że podany adres pamięci w tym procesie, 245 00:20:33,960 --> 00:20:38,800 jak to jest na stosie, czy coś, to zwróci wartość tego adresu pamięci 246 00:20:38,800 --> 00:20:41,960 ile proces wie. 247 00:20:41,960 --> 00:20:47,520 Ale jeśli nie 1234, że podany adres jest, jak to się dzieje na ziemi 248 00:20:47,520 --> 00:20:52,910 w pewnym niewielkim kawałkiem pamięci tutaj jest poza stos i poza stos 249 00:20:52,910 --> 00:20:57,200 i naprawdę nie używane, że to jest to, gdy pojawi się takie rzeczy jak segfaultów 250 00:20:57,200 --> 00:21:00,260 bo jesteś dotykając pamięć, że nie należy dotykać. 251 00:21:07,180 --> 00:21:09,340 Odnosi się to również - 252 00:21:09,340 --> 00:21:15,440 32-bitowy system, 32 bitów oznacza, że ​​masz 32 bitów do zdefiniowania adresu pamięci. 253 00:21:15,440 --> 00:21:22,970 To dlatego wskaźniki są 8 bajtów, bo 32 bity to 8 bajtów - lub 4 bajty. 254 00:21:22,970 --> 00:21:25,250 Wskaźniki są 4 bajty. 255 00:21:25,250 --> 00:21:33,680 Więc kiedy widzisz wskaźnik jak oxbfffff, czyli - 256 00:21:33,680 --> 00:21:40,080 W ramach danego programu można po prostu zbudować dowolną wskaźnik, 257 00:21:40,080 --> 00:21:46,330 wszędzie od ox0 do wołu 8 f's - FFFFFFFF. 258 00:21:46,330 --> 00:21:49,180 [Uczeń] nie można powiedzieć, że są 4 bajty? >> Tak. 259 00:21:49,180 --> 00:21:52,730 [Uczeń] Następnie każdy bajt będzie - >> [Bowden] szesnastkowa. 260 00:21:52,730 --> 00:21:59,360 Szesnastkowym - 5, 6, 7, 8. Więc wskaźników będziesz zawsze zobaczyć w systemie szesnastkowym. 261 00:21:59,360 --> 00:22:01,710 To jest po prostu, jak klasyfikujemy wskaźniki. 262 00:22:01,710 --> 00:22:05,240 Co 2 cyfry szesnastkowej jest 1 bajt. 263 00:22:05,240 --> 00:22:09,600 Więc nie będzie to 8 cyfr szesnastkowych dla 4 bajty. 264 00:22:09,600 --> 00:22:14,190 Więc każdy wskaźnik na systemie 32-bitowym będzie 4 bajty, 265 00:22:14,190 --> 00:22:18,550 co oznacza, że ​​w procesie można budować żadnych arbitralnych 4 bajty 266 00:22:18,550 --> 00:22:20,550 i zrobić z tego wskaźnika, 267 00:22:20,550 --> 00:22:32,730 co oznacza, że ​​o ile jest to świadome, może to zająć całe 2 do 32 bajtów pamięci. 268 00:22:32,730 --> 00:22:34,760 Mimo, że tak naprawdę nie ma dostępu do tego, 269 00:22:34,760 --> 00:22:40,190 nawet jeśli komputer ma tylko 512 megabajtów, to myśli, że ma tego dużo pamięci. 270 00:22:40,190 --> 00:22:44,930 A system operacyjny jest na tyle sprytny, że to będzie tylko przydzielić co faktycznie potrzebują. 271 00:22:44,930 --> 00:22:49,630 To nie po prostu przejść, oh, nowy proces: 4 koncerty. 272 00:22:49,630 --> 00:22:51,930 >> Tak. >> [Uczeń] Co wół na myśli? Dlaczego piszesz? 273 00:22:51,930 --> 00:22:54,980 To jest po prostu symbolem szesnastkowym. 274 00:22:54,980 --> 00:22:59,590 Kiedy widzisz numer startowy z wołu, kolejne rzeczy są szesnastkowym. 275 00:23:01,930 --> 00:23:05,760 [Uczeń] Miałeś wyjaśnić, co dzieje się, gdy program się kończy. >> Tak. 276 00:23:05,760 --> 00:23:09,480 Co się dzieje, gdy program się kończy to system operacyjny 277 00:23:09,480 --> 00:23:13,600 tylko usuwa mapowania, że ​​ma dla tych adresów, i to jest to. 278 00:23:13,600 --> 00:23:17,770 System operacyjny może teraz po prostu dać tej pamięci do innego programu do używania. 279 00:23:17,770 --> 00:23:19,490 [Uczeń] Dobra. 280 00:23:19,490 --> 00:23:24,800 Więc jeśli coś przeznaczyć na stercie lub stosu lub zmienne globalne lub cokolwiek, 281 00:23:24,800 --> 00:23:27,010 wszyscy zniknąć natychmiast kończy program 282 00:23:27,010 --> 00:23:32,120 ponieważ system operacyjny jest już wolny, aby dać tej pamięci do innego procesu. 283 00:23:32,120 --> 00:23:35,150 [Uczeń] Mimo że prawdopodobnie istnieją jeszcze wartości pisane? >> Tak. 284 00:23:35,150 --> 00:23:37,740 Wartości mogą nadal. 285 00:23:37,740 --> 00:23:41,570 To jest po prostu to będzie trudno dostać się do nich. 286 00:23:41,570 --> 00:23:45,230 Jest o wiele bardziej trudne do uzyskania na nich, niż to dostać w usuniętego pliku 287 00:23:45,230 --> 00:23:51,450 ponieważ usunięta rodzaj pliku siedzi tam przez długi czas, a dysk twardy jest dużo większy. 288 00:23:51,450 --> 00:23:54,120 Tak to się dzieje, aby zastąpić różne części pamięci 289 00:23:54,120 --> 00:23:58,640 zanim się to stanie zastąpić kawałek pamięci, że plik używany do być. 290 00:23:58,640 --> 00:24:04,520 Ale pamięć główna, RAM, możesz przełączać się o wiele szybciej, 291 00:24:04,520 --> 00:24:08,040 tak to się bardzo szybko zastąpione. 292 00:24:10,300 --> 00:24:13,340 Pytania o to czy coś innego? 293 00:24:13,340 --> 00:24:16,130 [Uczeń] Mam pytania o inny temat. >> Okay. 294 00:24:16,130 --> 00:24:19,060 Czy ktoś ma pytania w tej sprawie? 295 00:24:20,170 --> 00:24:23,120 >> Okay. Inny temat. >> [Uczeń] Dobra. 296 00:24:23,120 --> 00:24:26,550 Miałem przez niektóre z praktycznych testów, 297 00:24:26,550 --> 00:24:30,480 w jednej z nich mówił o sizeof 298 00:24:30,480 --> 00:24:35,630 i wartość, która zwraca lub różne typy zmiennych. >> Tak. 299 00:24:35,630 --> 00:24:45,060 I powiedział, że zarówno int i długo zarówno powrotu 4, więc są one zarówno 4 bajtów. 300 00:24:45,060 --> 00:24:48,070 Czy jest jakaś różnica między int i długi, czy jest to samo? 301 00:24:48,070 --> 00:24:50,380 Tak, że różnica. 302 00:24:50,380 --> 00:24:52,960 C standard - 303 00:24:52,960 --> 00:24:54,950 Jestem prawdopodobnie będzie bałagan. 304 00:24:54,950 --> 00:24:58,800 C standard jest po prostu to, co C jest oficjalną dokumentacją C. 305 00:24:58,800 --> 00:25:00,340 To jest to, co mówi. 306 00:25:00,340 --> 00:25:08,650 Więc C standard po prostu mówi, że char będzie zawsze i zawsze będzie 1 bajt. 307 00:25:10,470 --> 00:25:19,040 Wszystko potem - krótki zawsze jest zdefiniowane jako większa niż lub równa znak. 308 00:25:19,040 --> 00:25:23,010 To może być większy od, ale nie jest dodatni. 309 00:25:23,010 --> 00:25:31,940 Int jest zdefiniowane tak jak jest większa niż lub równa krótki. 310 00:25:31,940 --> 00:25:36,210 I tak długo jest zdefiniowane jako większa niż lub równa int. 311 00:25:36,210 --> 00:25:41,600 I długości czasu jest większa niż lub równa długości. 312 00:25:41,600 --> 00:25:46,610 Jedyne więc C Standard definiuje jest względne uporządkowanie wszystkiego. 313 00:25:46,610 --> 00:25:54,880 Rzeczywista ilość pamięci, że wszystko jest na ogół trwać do realizacji, 314 00:25:54,880 --> 00:25:57,640 ale jest całkiem dobrze określone w tym punkcie. >> [Uczeń] Dobra. 315 00:25:57,640 --> 00:26:02,490 Więc szorty są prawie zawsze będzie 2 bajty. 316 00:26:04,920 --> 00:26:09,950 Ints są prawie zawsze będzie to 4 bajty. 317 00:26:12,070 --> 00:26:15,340 Długie wyroby długie są prawie zawsze będzie to 8 bajtów. 318 00:26:17,990 --> 00:26:23,160 I tęskni, to zależy od tego, czy używasz 32-bitowej lub 64-bitowego systemu. 319 00:26:23,160 --> 00:26:27,450 Tak długo będzie odpowiadać typu systemu. 320 00:26:27,450 --> 00:26:31,920 Jeśli używasz 32-bitowego systemu, jak urządzenia, to będzie 4 bajty. 321 00:26:34,530 --> 00:26:42,570 Jeśli używasz 64-bit jak wiele nowszych komputerach, to będzie 8 bajtów. 322 00:26:42,570 --> 00:26:45,230 >> Ints są prawie zawsze 4 bajty na tym punkcie. 323 00:26:45,230 --> 00:26:47,140 Długie wyroby długie są prawie zawsze 8 bajtów. 324 00:26:47,140 --> 00:26:50,300 W przeszłości, w celu Ints używane tylko 2 bajty. 325 00:26:50,300 --> 00:26:56,840 Ale zauważ, że ten całkowicie spełnia wszystkie te relacje, powyżej i równe. 326 00:26:56,840 --> 00:27:01,280 Tak długo, doskonale może być taka sama jak liczba całkowita, 327 00:27:01,280 --> 00:27:04,030 i to również może mieć taki sam rozmiar jak długo długo. 328 00:27:04,030 --> 00:27:11,070 I to właśnie tak dzieje się, że 99,999% systemów, to będzie równa 329 00:27:11,070 --> 00:27:15,800 albo int lub long long. Zależy to tylko od 32-bit czy 64-bit. >> [Uczeń] Dobra. 330 00:27:15,800 --> 00:27:24,600 W pływaków, jak jest przecinek wyznaczone względem bitów? 331 00:27:24,600 --> 00:27:27,160 Lubię jako binarne? >> Tak. 332 00:27:27,160 --> 00:27:30,570 Nie musisz wiedzieć, że dla CS50. 333 00:27:30,570 --> 00:27:32,960 Ty nawet nie dowiedzieć się, że w 61. 334 00:27:32,960 --> 00:27:37,350 Nie dowiedzą się, że tak naprawdę w każdym kursie. 335 00:27:37,350 --> 00:27:42,740 To tylko reprezentacja. 336 00:27:42,740 --> 00:27:45,440 Zapomniałem dokładnie przydziały bitowych. 337 00:27:45,440 --> 00:27:53,380 Pomysł zmiennoprzecinkowych jest przydzielić określoną liczbę bitów do reprezentacji - 338 00:27:53,380 --> 00:27:56,550 Zasadniczo, wszystko jest w notacji naukowej. 339 00:27:56,550 --> 00:28:05,600 Więc przydzielić określoną liczbę bitów do reprezentowania samego numeru, jak 1,2345. 340 00:28:05,600 --> 00:28:10,200 I nigdy nie może reprezentować liczby z więcej niż 5 cyfr. 341 00:28:12,200 --> 00:28:26,300 Wtedy też przydzielić określoną liczbę bitów tak, że wydaje się być jak 342 00:28:26,300 --> 00:28:32,810 można tylko iść do pewnej liczby, jak to jest największy wykładnik można mieć, 343 00:28:32,810 --> 00:28:36,190 i można tylko iść w dół do pewnego wykładnika, 344 00:28:36,190 --> 00:28:38,770 jak to jest najmniejszy wykładnik możesz mieć. 345 00:28:38,770 --> 00:28:44,410 >> Nie pamiętam dokładnie sposób bity są przypisane do wszystkich tych wartości, 346 00:28:44,410 --> 00:28:47,940 ale pewna liczba bitów są dedykowane do 1,2345, 347 00:28:47,940 --> 00:28:50,930 kolejny pewna liczba bitów są dedykowane do wykładnika, 348 00:28:50,930 --> 00:28:55,670 i to tylko możliwe, aby stanowić wykładnik określonej wielkości. 349 00:28:55,670 --> 00:29:01,100 [Uczeń] I podwójnie? Jest to, że jak na dodatkowym pacy? >> Tak. 350 00:29:01,100 --> 00:29:07,940 To samo, co pływaka chyba teraz używasz 8 bajtów zamiast 4 bajtów. 351 00:29:07,940 --> 00:29:11,960 Teraz będziesz mieć możliwość korzystania z 9 cyfr lub 10 cyfr, 352 00:29:11,960 --> 00:29:16,630 i to będzie w stanie iść do 300, a nie 100. >> [Uczeń] Dobra. 353 00:29:16,630 --> 00:29:21,550 I unosi się również 4 bajty. >> Tak. 354 00:29:21,550 --> 00:29:27,520 Cóż, znowu, to chyba zależy od ogólnego w sprawie ogólnego wdrażania, 355 00:29:27,520 --> 00:29:30,610 ale pływaki są 4 bajty, dwuosobowe to 8. 356 00:29:30,610 --> 00:29:33,440 Doubles nazywane są podwójne, ponieważ są one dwukrotnie rozmiar pływaków. 357 00:29:33,440 --> 00:29:38,380 [Uczeń] Dobra. I są tam dwukrotnie podwaja? >> Nie ma. 358 00:29:38,380 --> 00:29:43,660 Myślę - >> [uczeń] Podoba długich tęskni? >> Tak. Myślę, że nie. Tak. 359 00:29:43,660 --> 00:29:45,950 [Uczeń] Na ubiegłorocznym teście było pytanie o głównej funkcji 360 00:29:45,950 --> 00:29:49,490 mające być częścią programu. 361 00:29:49,490 --> 00:29:52,310 Odpowiedź była, że ​​to nie musi być częścią programu. 362 00:29:52,310 --> 00:29:55,100 W jakiej sytuacji? To, co widziałem. 363 00:29:55,100 --> 00:29:59,090 [Bowden] Wydaje się - >> [uczeń] Jaka sytuacja? 364 00:29:59,090 --> 00:30:02,880 Masz problem? >> [Uczeń] Tak, z całą pewnością mogę wyciągnąć go. 365 00:30:02,880 --> 00:30:07,910 To nie musi być, technicznie, ale w zasadzie to będzie. 366 00:30:07,910 --> 00:30:10,030 [Uczeń] Widziałem jednego na inny Rok. 367 00:30:10,030 --> 00:30:16,220 To było jak Prawda czy fałsz: ważne - >> Och, plik c.? 368 00:30:16,220 --> 00:30:18,790 . [Uczeń] Każdy plik c musi mieć - [zarówno w mowie na raz - niezrozumiały] 369 00:30:18,790 --> 00:30:21,120 Okay. Więc to jest oddzielne. 370 00:30:21,120 --> 00:30:26,800 >> Plik. C po prostu musi zawierać funkcje. 371 00:30:26,800 --> 00:30:32,400 Możesz skompilować plik do kodu maszynowego, binarny, cokolwiek, 372 00:30:32,400 --> 00:30:36,620 przy czym nie jest wykonywalny jeszcze. 373 00:30:36,620 --> 00:30:39,420 Ważne wykonywalny musi mieć główną funkcję. 374 00:30:39,420 --> 00:30:45,460 Możesz napisać 100 funkcje w 1 pliku, ale nie najważniejsze 375 00:30:45,460 --> 00:30:48,800 a następnie skompilować, że w dół na dwójkową 376 00:30:48,800 --> 00:30:54,460 następnie napisać inny plik, który ma tylko główny, ale wywołuje kilka tych funkcji 377 00:30:54,460 --> 00:30:56,720 w tym pliku binarnego tutaj. 378 00:30:56,720 --> 00:31:01,240 I tak, gdy robisz wykonywalny, to co robi linker 379 00:31:01,240 --> 00:31:05,960 jest ona łączy te 2 pliki binarne do pliku wykonywalnego. 380 00:31:05,960 --> 00:31:11,400 Tak więc. Pliku C nie musi mieć funkcję głównego ogóle. 381 00:31:11,400 --> 00:31:19,220 I na dużych bazach kodu zobaczysz tysiące plików. C i 1 plik główny. 382 00:31:23,960 --> 00:31:26,110 Więcej pytań? 383 00:31:29,310 --> 00:31:31,940 [Uczeń] Nie było kolejne pytanie. 384 00:31:31,940 --> 00:31:36,710 To powiedział, aby to kompilator. Prawda czy fałsz? 385 00:31:36,710 --> 00:31:42,030 A odpowiedź była fałszywa, a ja zrozumiałem, dlaczego to nie jest tak Clang. 386 00:31:42,030 --> 00:31:44,770 Ale to, co my nazywamy się, jeśli nie jest? 387 00:31:44,770 --> 00:31:49,990 Marka jest w zasadzie tylko - można zobaczyć dokładnie to, co nazywa go. 388 00:31:49,990 --> 00:31:52,410 Ale to tylko wykonywaniem poleceń. 389 00:31:53,650 --> 00:31:55,650 Make. 390 00:31:58,240 --> 00:32:00,870 Mogę ciągnąć tego. Tak. 391 00:32:10,110 --> 00:32:13,180 Oh, yeah. Dodać też robi. 392 00:32:13,180 --> 00:32:17,170 Mówi to celem jest narzędzie make automatycznie określić 393 00:32:17,170 --> 00:32:19,610 która część dużego programu wymaga rekompilacji 394 00:32:19,610 --> 00:32:22,350 i wydawania poleceń przekompilować je. 395 00:32:22,350 --> 00:32:27,690 Można zrobić, aby pliki, które są absolutnie ogromne. 396 00:32:27,690 --> 00:32:33,210 Marka patrzy na znaczniki czasu plików i, jak powiedziałem wcześniej, 397 00:32:33,210 --> 00:32:36,930 można kompilować poszczególne pliki w dół, i to nie jest, aż dojdziesz do linker 398 00:32:36,930 --> 00:32:39,270 że są one połączone do pliku wykonywalnego. 399 00:32:39,270 --> 00:32:43,810 Więc jeśli masz 10 różnych plików i wprowadzić zmiany w 1 z nich, 400 00:32:43,810 --> 00:32:47,870 to co marka ma zamiar zrobić, to po prostu przekompilować że 1 plik 401 00:32:47,870 --> 00:32:50,640 a następnie ponownie połączyć wszystko razem. 402 00:32:50,640 --> 00:32:53,020 Ale jest znacznie głupszy niż to. 403 00:32:53,020 --> 00:32:55,690 To do ciebie, aby całkowicie zdefiniować, że to jest to, co powinno się robić. 404 00:32:55,690 --> 00:32:59,560 Jest domyślnie posiada zdolność do rozpoznawania tych rzeczy czasowe, 405 00:32:59,560 --> 00:33:03,220 ale można zapisać plik make nic robić. 406 00:33:03,220 --> 00:33:09,150 Możesz napisać, aby plik, tak aby po wpisaniu się to tylko cd do innego katalogu. 407 00:33:09,150 --> 00:33:15,560 Byłem sfrustrowany, bo wszystko tack wewnątrz mojego Appliance 408 00:33:15,560 --> 00:33:21,740 a potem wyświetlić PDF z Mac. 409 00:33:21,740 --> 00:33:30,720 >> Więc idę do Findera i mogę zrobić: Idź, Połącz się z serwerem, 410 00:33:30,720 --> 00:33:36,950 i połączyć się z serwerem jest mój Appliance, a potem otworzyć plik PDF 411 00:33:36,950 --> 00:33:40,190 który pobiera kompilowane przez LaTeX. 412 00:33:40,190 --> 00:33:49,320 Ale byłem sfrustrowany, bo za każdym razem musiałem odświeżyć PDF, 413 00:33:49,320 --> 00:33:53,900 Miałem go skopiować do określonego katalogu, który może uzyskać dostęp do 414 00:33:53,900 --> 00:33:57,710 i robiło się irytujące. 415 00:33:57,710 --> 00:34:02,650 Zamiast więc napisałem plik make, trzeba określić, jak to sprawia, że ​​rzeczy. 416 00:34:02,650 --> 00:34:06,130 Jak zrobić to w PDF LaTeX. 417 00:34:06,130 --> 00:34:10,090 Podobnie jak każdy inny plik make - lub Chyba nie widziałeś plików make, 418 00:34:10,090 --> 00:34:13,510 ale mamy w urządzeniu globalny plik sprawiają, że po prostu mówi: 419 00:34:13,510 --> 00:34:16,679 Jeśli kompilujesz plik C, użyj dzyń. 420 00:34:16,679 --> 00:34:20,960 I tak oto w moim pliku sprawi że robię mówię, 421 00:34:20,960 --> 00:34:25,020 ten plik masz zamiar kompilować z PDF LaTeX. 422 00:34:25,020 --> 00:34:27,889 A więc jest to PDF LaTeX, który robi kompilację. 423 00:34:27,889 --> 00:34:31,880 Producent nie jest kompilacją. To jest po prostu wykonywania tych poleceń w kolejności I określony. 424 00:34:31,880 --> 00:34:36,110 Więc działa LaTeX PDF, kopiuje je do katalogu I ma to być skopiowane, 425 00:34:36,110 --> 00:34:38,270 to cd do katalogu i robi inne rzeczy, 426 00:34:38,270 --> 00:34:42,380 ale to nie jest rozpoznać kiedy zmiany plików, 427 00:34:42,380 --> 00:34:45,489 i czy to zmieni, to będzie uruchomić polecenia że to ma działać 428 00:34:45,489 --> 00:34:48,760 gdy zmiany plików. >> [Uczeń] Dobra. 429 00:34:50,510 --> 00:34:54,420 Nie wiem, gdzie globalne pliki zwierne są dla mnie sprawdzić. 430 00:34:57,210 --> 00:35:04,290 Inne pytania? Coś z przeszłości quizy? Wszelkie rzeczy wskaźnik? 431 00:35:06,200 --> 00:35:08,730 Istnieją subtelne rzeczy, ze wskazówkami, jak - 432 00:35:08,730 --> 00:35:10,220 I nie zamierzam być w stanie znaleźć pytanie quizu na nim - 433 00:35:10,220 --> 00:35:16,250 ale tak jak tego typu rzeczy. 434 00:35:19,680 --> 00:35:24,060 Upewnij się, że rozumiesz, że kiedy mówię, int * x * y - 435 00:35:24,890 --> 00:35:28,130 To nie jest dokładnie to, coś tu chyba. 436 00:35:28,130 --> 00:35:32,140 Ale jak * x * y, to są 2 zmienne, które są na stosie. 437 00:35:32,140 --> 00:35:37,220 Kiedy mówię, że x = malloc (sizeof (int)), x jest wciąż zmienna na stosie, 438 00:35:37,220 --> 00:35:41,180 malloc jest jakiś blok na w kupie, a my mając punkt X na stertę. 439 00:35:41,180 --> 00:35:43,900 >> Więc coś na punkty stosu do stosu. 440 00:35:43,900 --> 00:35:48,100 Kiedykolwiek malloc niczego, jesteś nieuchronnie przechowywanie go wewnątrz wskaźnika. 441 00:35:48,100 --> 00:35:55,940 Tak, że wskaźnik jest na stosie, malloced blok jest na stercie. 442 00:35:55,940 --> 00:36:01,240 Wielu ludzi gubi i powiedzieć int * x = malloc; x jest na stercie. 443 00:36:01,240 --> 00:36:04,100 No Co x wskazuje na to na stercie. 444 00:36:04,100 --> 00:36:08,540 x sam w sobie jest na stosie, chyba że z jakiegoś powodu masz x będzie zmienną globalną, 445 00:36:08,540 --> 00:36:11,960 w tym przypadku, aby być w stanie innym regionie pamięci. 446 00:36:13,450 --> 00:36:20,820 Więc śledzenie te skrzynki i strzałka schematy są dość powszechne w quizie. 447 00:36:20,820 --> 00:36:25,740 Lub jeśli nie jest na quizie 0, to będzie na quizie 1. 448 00:36:27,570 --> 00:36:31,940 Powinieneś wiedzieć, wszystkie z nich, kroki w opracowaniu 449 00:36:31,940 --> 00:36:35,740 ponieważ trzeba było odpowiedzieć na pytania dotyczące tych. Tak. 450 00:36:35,740 --> 00:36:38,940 [Student] Czy możemy przejść nad tymi krokami - >> Jasne. 451 00:36:48,340 --> 00:36:58,640 Przed schodami i kompilacji mamy wstępne przetwarzanie, 452 00:36:58,640 --> 00:37:16,750 kompilowania, montaż i łączenie. 453 00:37:16,750 --> 00:37:21,480 Przerób. Co z tego? 454 00:37:29,720 --> 00:37:32,290 To najprostszy krok - dobrze, nie jak - 455 00:37:32,290 --> 00:37:35,770 to nie znaczy, powinno być oczywiste, ale jest to najprostszy krok. 456 00:37:35,770 --> 00:37:38,410 Macie może wdrożyć go sami. Tak. 457 00:37:38,410 --> 00:37:43,410 [Uczeń] Weź to, co masz w pliku zawiera tak i kopiuje, a następnie definiuje również. 458 00:37:43,410 --> 00:37:49,250 To wygląda na takie rzeczy jak # include i # define, 459 00:37:49,250 --> 00:37:53,800 i to po prostu kopie i pasty, co to właściwie znaczy. 460 00:37:53,800 --> 00:37:59,240 Więc kiedy mówisz # include cs50.h, preprocesor jest kopiowanie i wklejanie cs50.h 461 00:37:59,240 --> 00:38:01,030 do tej linii. 462 00:38:01,030 --> 00:38:06,640 Kiedy mówisz # define x być 4, preprocesor przechodzi całego programu 463 00:38:06,640 --> 00:38:10,400 i zastępuje wszystkie wystąpienia X z 4. 464 00:38:10,400 --> 00:38:17,530 Więc preprocesor ma poprawny plik C i wyprowadza poprawny plik C 465 00:38:17,530 --> 00:38:20,300 jeżeli rzeczy zostały skopiowane i wklejone. 466 00:38:20,300 --> 00:38:24,230 Więc teraz kompilacji. Co z tego? 467 00:38:25,940 --> 00:38:28,210 [Uczeń] To idzie z C na binarny. 468 00:38:28,210 --> 00:38:30,970 >> [Bowden] To nie przejść całą drogę na binarny. 469 00:38:30,970 --> 00:38:34,220 [Uczeń] do kodu maszynowego, a następnie? >> To nie jest kod maszynowy. 470 00:38:34,220 --> 00:38:35,700 [Uczeń] Assembly? >> Assembly. 471 00:38:35,700 --> 00:38:38,890 To idzie do Zgromadzenia zanim przejdzie całą drogę do kodu w C, 472 00:38:38,890 --> 00:38:45,010 i większość języków coś jak to zrobić. 473 00:38:47,740 --> 00:38:50,590 Wybrać dowolny język wysokiego poziomu, a jeśli masz zamiar go skompilować, 474 00:38:50,590 --> 00:38:52,390 prawdopodobnie skompilować w krokach. 475 00:38:52,390 --> 00:38:58,140 Pierwszy to będzie skompilować Pythona do C, to to się skompilować C do Zgromadzenia, 476 00:38:58,140 --> 00:39:01,600 a następnie Zgromadzenie będzie tłumaczone na binarny. 477 00:39:01,600 --> 00:39:07,800 Więc kompilacji przyniesie to z C do Zgromadzenia. 478 00:39:07,800 --> 00:39:12,130 Słowo kompilacji zwykle oznacza doprowadzenia z wyższego poziomu 479 00:39:12,130 --> 00:39:14,340 do dolnego poziomu języka programowania. 480 00:39:14,340 --> 00:39:19,190 Więc to jest tylko etap kompilacji, gdzie zacząć języku wysokiego poziomu 481 00:39:19,190 --> 00:39:23,270 i kończy się w języku niskiego poziomu, i dlatego nazywany jest etapem kompilacji. 482 00:39:25,280 --> 00:39:33,370 [Uczeń] Podczas kompilacji, powiedzmy, że zrobiłeś # include cs50.h. 483 00:39:33,370 --> 00:39:42,190 Will kompilator recompile cs50.h jak funkcji, które są tam, 484 00:39:42,190 --> 00:39:45,280 i tłumaczyć, że do kodu Zgromadzenia, jak również, 485 00:39:45,280 --> 00:39:50,830 czy będzie to skopiować i wkleić coś, co zostało wcześniej Zgromadzenie? 486 00:39:50,830 --> 00:39:56,910 cs50.h będzie dość dużo nie kończy się w Zgromadzeniu. 487 00:39:59,740 --> 00:40:03,680 Rzeczy jak prototypów funkcji i rzeczy są tylko dla Ciebie, aby być ostrożnym. 488 00:40:03,680 --> 00:40:09,270 To gwarantuje, że kompilator może sprawdzić takie rzeczy jak dzwonisz funkcji 489 00:40:09,270 --> 00:40:12,910 z odpowiednich typów powrotu i odpowiednich argumentów i rzeczy. 490 00:40:12,910 --> 00:40:18,350 >> Więc cs50.h będzie preprocesowane do pliku, a następnie, kiedy to kompilacja 491 00:40:18,350 --> 00:40:22,310 Jest to w zasadzie wyrzucić po daje pewność, że wszystko jest nazywany pełnym zakresie. 492 00:40:22,310 --> 00:40:29,410 Ale funkcje zdefiniowane w CS50 biblioteki, które są oddzielone od cs50.h, 493 00:40:29,410 --> 00:40:33,610 tych, którzy nie będą osobno skompilowane. 494 00:40:33,610 --> 00:40:37,270 Które rzeczywiście zstąpił na etapie łączenia, więc my się do tego w sekundę. 495 00:40:37,270 --> 00:40:40,100 Ale po pierwsze, to, co jest montaż? 496 00:40:41,850 --> 00:40:44,500 [Uczeń] Montaż na binarny? >> Tak. 497 00:40:46,300 --> 00:40:48,190 Montaż. 498 00:40:48,190 --> 00:40:54,710 Nie nazywamy go kompilacji, ponieważ Zgromadzenie jest prawie czysty tłumaczenie binarny. 499 00:40:54,710 --> 00:41:00,230 Jest bardzo mało logika przechodząc od Zgromadzenia na binarny. 500 00:41:00,230 --> 00:41:03,180 To tak, jak patrzy w górę w tabeli, oh, mamy tej instrukcji; 501 00:41:03,180 --> 00:41:06,290 który odpowiada na binarny 01110. 502 00:41:10,200 --> 00:41:15,230 I tak pliki montaż ogólnie wyjścia są pliki. Ö. 503 00:41:15,230 --> 00:41:19,020 I pliki. O tym, co mówiliśmy wcześniej, 504 00:41:19,020 --> 00:41:21,570 Jak pliku nie jest konieczne, aby główny funkcji. 505 00:41:21,570 --> 00:41:27,640 Każdy plik może być zestawiane w dół do pliku. O ile jest to prawidłowy plik C. 506 00:41:27,640 --> 00:41:30,300 To może być zestawiane w dół. O. 507 00:41:30,300 --> 00:41:43,030 Teraz, łącząc to, co rzeczywiście przynosi bukiet. Pliki o i prowadzi je do pliku wykonywalnego. 508 00:41:43,030 --> 00:41:51,110 A więc to, co robi, to może linking myślisz o CS50 bibliotece pliku. O. 509 00:41:51,110 --> 00:41:56,980 Jest już skompilowany plik binarny. 510 00:41:56,980 --> 00:42:03,530 I tak podczas kompilacji plik, Twój hello.c, która wywołuje GetString, 511 00:42:03,530 --> 00:42:06,360 hello.c pobiera skompilowany dół hello.o, 512 00:42:06,360 --> 00:42:08,910 hello.o jest teraz w formacie binarnym. 513 00:42:08,910 --> 00:42:12,830 Wykorzystuje GetString, więc musi przejść na cs50.o, 514 00:42:12,830 --> 00:42:16,390 i linker smooshes je razem i kopiuje getString do tego pliku 515 00:42:16,390 --> 00:42:20,640 i wychodzi z pliku wykonywalnego, który ma wszystkie funkcje, których potrzebuje. 516 00:42:20,640 --> 00:42:32,620 Więc cs50.o nie jest faktycznie O plik, ale to jest na tyle blisko, że nie ma zasadniczej różnicy. 517 00:42:32,620 --> 00:42:36,880 Więc łączenie tylko przynosi kilka plików razem 518 00:42:36,880 --> 00:42:41,390 że oddzielnie zawierać wszystkie funkcje potrzebne do korzystania z 519 00:42:41,390 --> 00:42:46,120 i tworzy plik wykonywalny, który będzie faktycznie działać. 520 00:42:48,420 --> 00:42:50,780 >> A więc to jest także to, co mówiliśmy przed 521 00:42:50,780 --> 00:42:55,970 gdzie można mieć 1000. plików C, skompilować je wszystkie. Pliki o, 522 00:42:55,970 --> 00:43:00,040 co prawdopodobnie trochę potrwać, a następnie zmienić 1 plik. c. 523 00:43:00,040 --> 00:43:05,480 Trzeba tylko przebudować ten 1 plik. C, a następnie ponownie połączyć wszystkiego innego, 524 00:43:05,480 --> 00:43:07,690 połączyć wszystko razem. 525 00:43:09,580 --> 00:43:11,430 [Uczeń] Gdy mamy połączenie piszemy lcs50? 526 00:43:11,430 --> 00:43:20,510 Tak, tak lcs50. Że sygnały flagę do łącznika, które powinny być wiążące w tej bibliotece. 527 00:43:26,680 --> 00:43:28,910 Pytania? 528 00:43:41,310 --> 00:43:46,860 Czy zaszliśmy nad binarnym innym niż to 5 sekund na pierwszym wykładzie? 529 00:43:50,130 --> 00:43:53,010 Myślę, że nie. 530 00:43:55,530 --> 00:43:58,820 Powinieneś wiedzieć wszystko o wielkim Os że zaszliśmy nad, 531 00:43:58,820 --> 00:44:02,670 i powinny być w stanie, jeśli dał ci funkcji 532 00:44:02,670 --> 00:44:09,410 powinieneś być w stanie powiedzieć, że jest duża O, mniej więcej. Albo dobrze, big O jest szorstka. 533 00:44:09,410 --> 00:44:15,300 Więc jeśli widzisz zagnieżdżone pętli pętli na tej samej ilości rzeczy, 534 00:44:15,300 --> 00:44:22,260 jak int i, i > [uczeń] n kwadratu. >> To wydaje się być n do kwadratu. 535 00:44:22,260 --> 00:44:25,280 Jeśli potrójna zagnieżdżone, to wydaje się być n do sześcianu. 536 00:44:25,280 --> 00:44:29,330 Tak więc tego typu rzeczy powinny być w stanie wskazać natychmiast. 537 00:44:29,330 --> 00:44:33,890 Musisz znać rodzaj wstawiania i sortowanie bąbelkowe i scalania sortowania i wszystkie z nich. 538 00:44:33,890 --> 00:44:41,420 Łatwiej jest zrozumieć, dlaczego są te n do kwadratu, a n log n a wszystko to 539 00:44:41,420 --> 00:44:47,810 bo myślę, że był na quizu jeden rok, gdzie w zasadzie dał ci 540 00:44:47,810 --> 00:44:55,050 Realizacja sortowanie bąbelkowe i powiedział: "Co to jest czas działania tej funkcji?" 541 00:44:55,050 --> 00:45:01,020 Tak więc, jeśli uznają ją za sortowanie bąbelkowe, to można od razu powiedzieć, n do kwadratu. 542 00:45:01,020 --> 00:45:05,470 Ale jeśli tylko spojrzeć na to, że nawet nie zdawać sobie sprawę, że to coś w rodzaju bańki; 543 00:45:05,470 --> 00:45:08,990 można po prostu powiedzieć, że robi to i to. To jest n do kwadratu. 544 00:45:12,350 --> 00:45:14,710 [Student] Czy są jakieś trudne przykłady można wymyślić, 545 00:45:14,710 --> 00:45:20,370 jak podobny pomysł na zastanawianie się? 546 00:45:20,370 --> 00:45:24,450 >> Nie sądzę, byśmy daje żadnych trudnych przykładów. 547 00:45:24,450 --> 00:45:30,180 Rzeczą sortowanie bąbelkowe jest tak trudne, jak pójdziemy, 548 00:45:30,180 --> 00:45:36,280 a nawet, że tak długo, jak rozumiem, że jesteś iteracja tablicy 549 00:45:36,280 --> 00:45:41,670 dla każdego elementu w tablicy, która ma być coś, co jest n do kwadratu. 550 00:45:45,370 --> 00:45:49,940 Istnieją ogólne pytania, jak tu mamy - Oh. 551 00:45:55,290 --> 00:45:58,530 Tylko na drugi dzień, Doug stwierdził, "I wymyślili algorytm, który może uporządkować tablicę 552 00:45:58,530 --> 00:46:01,780 "Z n liczb w czasie O (log n) czas!" 553 00:46:01,780 --> 00:46:04,900 Więc skąd mamy wiedzieć, że to niemożliwe? 554 00:46:04,900 --> 00:46:08,850 [Niesłyszalne reakcja studentów] >> Tak. 555 00:46:08,850 --> 00:46:13,710 Przynajmniej, trzeba dotknąć każdego elementu w tablicy, 556 00:46:13,710 --> 00:46:16,210 więc jest to niemożliwe, aby sortować tablicę - 557 00:46:16,210 --> 00:46:20,850 Jeżeli wszystko jest w porządku nieposortowanych, potem idziesz do dotykania wszystkiego w tablicy, 558 00:46:20,850 --> 00:46:25,320 więc nie da się to zrobić w mniej niż O n. 559 00:46:27,430 --> 00:46:30,340 [Uczeń] Pokazałeś nam, że przykład jest w stanie to zrobić w O n 560 00:46:30,340 --> 00:46:33,920 jeśli używasz dużo pamięci. >> Tak. 561 00:46:33,920 --> 00:46:37,970 I that's - I zapomnieć, co that's - Czy liczenie sortowanie? 562 00:46:47,360 --> 00:46:51,330 Hmm. Jest to całkowita algorytm sortowania. 563 00:46:59,850 --> 00:47:05,100 Szukałem specjalnej nazwy dla tego, że nie mogłem sobie przypomnieć w zeszłym tygodniu. 564 00:47:05,100 --> 00:47:13,000 Tak. Są to typy, które może wykonać różnego rodzaju rzeczy w Big O n. 565 00:47:13,000 --> 00:47:18,430 Ale istnieją pewne ograniczenia, jak można używać tylko liczb całkowitych do pewnej liczby. 566 00:47:20,870 --> 00:47:24,560 Plus, jeśli próbujesz sortować that's coś - 567 00:47:24,560 --> 00:47:30,750 Jeśli tablica jest 012, -12, 151, 4 mln zł, 568 00:47:30,750 --> 00:47:35,120 wtedy, że jeden element będzie całkowicie zrujnować całą sortowanie. 569 00:47:42,060 --> 00:47:44,030 >> Pytania? 570 00:47:49,480 --> 00:47:58,870 [Uczeń] Jeśli masz funkcji rekurencyjnej i to właśnie sprawia, że ​​wywołania rekurencyjne 571 00:47:58,870 --> 00:48:02,230 w instrukcji return, to tail recursive, 572 00:48:02,230 --> 00:48:07,360 i tak nie będzie, że więcej pamięci podczas wykonywania 573 00:48:07,360 --> 00:48:12,550 czy to przynajmniej użyj porównywalnego pamięć jako iteracyjne rozwiązanie? 574 00:48:12,550 --> 00:48:14,530 [Bowden] Tak. 575 00:48:14,530 --> 00:48:19,840 To prawdopodobnie będzie nieco wolniejszy, ale nie bardzo. 576 00:48:19,840 --> 00:48:23,290 Tail recursive jest całkiem dobra. 577 00:48:23,290 --> 00:48:32,640 Patrząc ponownie na ramki o, powiedzmy, że mamy główną 578 00:48:32,640 --> 00:48:42,920 i mamy int bar (int x), czy coś. 579 00:48:42,920 --> 00:48:52,310 To nie idealne funkcja rekurencyjna, ale bar return (x - 1). 580 00:48:52,310 --> 00:48:57,620 Tak oczywiście, to jest błędne. Musisz przypadki bazowe i takie tam. 581 00:48:57,620 --> 00:49:00,360 Ale idea jest taka, że ​​jest to ogon recursive, 582 00:49:00,360 --> 00:49:06,020 co oznacza, gdy belkę nazywa to dostanie ramkę stosu. 583 00:49:09,550 --> 00:49:12,440 W tej ramce stosu nie będzie mały blok pamięci 584 00:49:12,440 --> 00:49:17,490 że odpowiada jej argument x. 585 00:49:17,490 --> 00:49:25,840 I tak powiedzmy główny dzieje wywołać bar (100); 586 00:49:25,840 --> 00:49:30,050 Więc x zamierza rozpocząć się jak 100. 587 00:49:30,050 --> 00:49:35,660 Jeśli kompilator uznaje, że to ogon funkcja rekurencyjna, 588 00:49:35,660 --> 00:49:38,540 następnie, gdy bar sprawia, że ​​jej wywołanie rekurencyjne do baru, 589 00:49:38,540 --> 00:49:45,490 zamiast tworzyć nową ramkę stosu, który jest gdzie stos zaczyna rosnąć w dużej mierze, 590 00:49:45,490 --> 00:49:48,220 w końcu to będzie działać na stercie, a następnie dostać segfaultów 591 00:49:48,220 --> 00:49:51,590 ponieważ pamięć zaczyna kolizji. 592 00:49:51,590 --> 00:49:54,830 >> Więc zamiast tworzyć własne ramki stosu, może sobie uświadomić, 593 00:49:54,830 --> 00:49:59,080 hej, nigdy naprawdę muszę wrócić do tej ramki stosu, 594 00:49:59,080 --> 00:50:08,040 więc zamiast ja po prostu wymienić ten argument z 99, a następnie uruchomić pasek wszystkim. 595 00:50:08,040 --> 00:50:11,810 A potem zrobi to ponownie i osiągnie pasek powrotu (x - 1), 596 00:50:11,810 --> 00:50:17,320 i zamiast tworzenia nowej ramki stosu, to po prostu zastąpić obecną argumentu z 98 597 00:50:17,320 --> 00:50:20,740 a następnie wrócić do samego początku barze. 598 00:50:23,860 --> 00:50:30,430 Operacje te, zastępując to 1 wartość na stosie i skacze z powrotem do początku, 599 00:50:30,430 --> 00:50:32,430 są dość wydajne. 600 00:50:32,430 --> 00:50:41,500 Tak więc, nie tylko jest to samo zastosowanie jako oddzielne pamięci, która jest funkcją iteracyjny 601 00:50:41,500 --> 00:50:45,390 bo jesteś tylko przy użyciu 1 stosu ramki, ale nie jesteś cierpienie downsides 602 00:50:45,390 --> 00:50:47,240 konieczności wywoływania funkcji. 603 00:50:47,240 --> 00:50:50,240 Funkcje połączeń może być nieco droższe, ponieważ musi zrobić wszystko, to ustawienie 604 00:50:50,240 --> 00:50:52,470 i przerywaniem i wszystkie te rzeczy. 605 00:50:52,470 --> 00:50:58,160 Więc to rekurencja ogon jest dobry. 606 00:50:58,160 --> 00:51:01,170 [Uczeń] Dlaczego nie tworzyć nowe kroki? 607 00:51:01,170 --> 00:51:02,980 Ponieważ realizuje nie musi. 608 00:51:02,980 --> 00:51:07,800 Wezwanie do paska jest właśnie zwrócenie wywołanie rekurencyjne. 609 00:51:07,800 --> 00:51:12,220 Więc nie trzeba robić nic z wartości zwracanej. 610 00:51:12,220 --> 00:51:15,120 To po prostu będzie natychmiast zwrócić. 611 00:51:15,120 --> 00:51:20,530 Więc to po prostu się wymienić swoją argumentację i zacząć od nowa. 612 00:51:20,530 --> 00:51:25,780 A także, jeśli nie mają ogon rekurencyjną wersję, 613 00:51:25,780 --> 00:51:31,460 wtedy otrzymasz wszystkie te bary, w których, gdy ten bar zwraca 614 00:51:31,460 --> 00:51:36,010 ma wrócić jego wartość do tego, to bar natychmiast powraca 615 00:51:36,010 --> 00:51:39,620 i zwraca jego wartość do tego, to jest to po prostu się do natychmiastowego zwrotu 616 00:51:39,620 --> 00:51:41,350 i zwraca jego wartość do tego. 617 00:51:41,350 --> 00:51:45,350 Więc oszczędność to popping wszystkie te rzeczy off stosu 618 00:51:45,350 --> 00:51:48,730 ponieważ zwracana wartość jest tylko będzie przekazywane z powrotem do góry i tak. 619 00:51:48,730 --> 00:51:55,400 Więc dlaczego nie po prostu zastąpić naszą argumentację zaktualizowanego argument i zacząć od początku? 620 00:51:57,460 --> 00:52:01,150 Jeśli funkcja nie tail recursive jest, jeśli można zrobić coś takiego - 621 00:52:01,150 --> 00:52:07,530 [Uczeń], jeśli bar (x + 1). >> Tak. 622 00:52:07,530 --> 00:52:11,770 >> Więc jeśli umieścić go w stanie, to robisz coś z wartości zwracanej. 623 00:52:11,770 --> 00:52:16,260 Lub nawet jeśli tylko zrobić zwrot 2 * bar (x - 1). 624 00:52:16,260 --> 00:52:23,560 Więc teraz bar (x - 1) musi wrócić w celu użycia go do obliczenia 2 razy tej wartości, 625 00:52:23,560 --> 00:52:26,140 więc teraz nie potrzebuje osobne ramki stosu, 626 00:52:26,140 --> 00:52:31,180 i teraz, nie ważne jak bardzo się starasz, masz zamiar trzeba - 627 00:52:31,180 --> 00:52:34,410 To nie jest ogon rekurencyjne. 628 00:52:34,410 --> 00:52:37,590 [Uczeń] Chciałbym spróbować wnieść rekursji do dążyć do rekursji ogonowej - 629 00:52:37,590 --> 00:52:41,450 [Bowden] W idealnym świecie, ale w CS50 nie muszą. 630 00:52:43,780 --> 00:52:49,280 W celu uzyskania rekurencji ogon, ogólnie, należy założyć dodatkowy argument 631 00:52:49,280 --> 00:52:53,550 gdzie bar będzie int x do y. 632 00:52:53,550 --> 00:52:56,990 a y odpowiada ostatecznej rzeczą, którą chcesz, aby powrócić. 633 00:52:56,990 --> 00:53:03,650 Więc to będziesz wrócimy bar (x - 1), 2 * y. 634 00:53:03,650 --> 00:53:09,810 Tak, że to tylko na wysokim poziomie, jak przekształcić rzeczy się ogon rekurencyjne. 635 00:53:09,810 --> 00:53:13,790 Ale dodatkowy argument - 636 00:53:13,790 --> 00:53:17,410 A potem w końcu po osiągnięciu przypadku bazowego, po prostu wrócić y 637 00:53:17,410 --> 00:53:22,740 dlatego, że gromadziły się przez cały czas, zwracanej wartości, które chcesz. 638 00:53:22,740 --> 00:53:27,280 Jesteś rodzaju robią to iteracyjnie ale stosując cykliczne rozmowy. 639 00:53:32,510 --> 00:53:34,900 Pytania? 640 00:53:34,900 --> 00:53:39,890 [Uczeń] Może o arytmetyce wskaźnika, podobnie jak przy użyciu ciągów. >> Jasne. 641 00:53:39,890 --> 00:53:43,610 Arytmetyczna wskaźnika. 642 00:53:43,610 --> 00:53:48,440 Podczas korzystania z ciągów jest łatwe, ponieważ ciągi są char gwiazdy, 643 00:53:48,440 --> 00:53:51,860 znaki są zawsze i zawsze jeden bajt, 644 00:53:51,860 --> 00:53:57,540 i tak arytmetyczna wskaźnika odpowiada regularnie arytmetyki, gdy masz do czynienia z ciągów. 645 00:53:57,540 --> 00:54:08,790 Powiedzmy, char * s = "hello". 646 00:54:08,790 --> 00:54:11,430 Mamy więc blok w pamięci. 647 00:54:19,490 --> 00:54:22,380 Potrzebuje 6 bajtów, ponieważ zawsze trzeba null terminatora. 648 00:54:22,380 --> 00:54:28,620 I char * s będzie wskazywać na początku tablicy. 649 00:54:28,620 --> 00:54:32,830 Więc ów wskazuje tam. 650 00:54:32,830 --> 00:54:36,710 Teraz, to jest w zasadzie jak każda tablica działa 651 00:54:36,710 --> 00:54:40,780 niezależnie od tego, czy to powrót przez malloc czy to na stosie. 652 00:54:40,780 --> 00:54:47,110 Każda tablica jest zasadniczo wskaźnik początku tablicy 653 00:54:47,110 --> 00:54:53,640 a każde działanie tablicy, każdy indeksowanie, jest po prostu wchodząc w tej tablicy pewne przesunięcie. 654 00:54:53,640 --> 00:55:05,360 >> Więc kiedy mówię coś jak s [3], to będzie s i liczenia 3 znaki cala 655 00:55:05,360 --> 00:55:12,490 Więc s [3], mamy 0, 1, 2, 3, więc s [3] ma zamiar odnieść się do tej l. 656 00:55:12,490 --> 00:55:20,460 [Uczeń] A mogliśmy osiągnąć taką samą wartość, wykonując s + 3, a następnie gwiazda nawiasy? 657 00:55:20,460 --> 00:55:22,570 Tak. 658 00:55:22,570 --> 00:55:26,010 Jest to równoważne * (S + 3); 659 00:55:26,010 --> 00:55:31,240 i że jest zawsze i zawsze równoważne nieważne co robisz. 660 00:55:31,240 --> 00:55:34,070 Nigdy nie należy używać składni montażowej. 661 00:55:34,070 --> 00:55:37,770 Zawsze możesz użyć * (y + 3) składni. 662 00:55:37,770 --> 00:55:40,180 Ludzie mają tendencję do jak składni wspornika, choć. 663 00:55:40,180 --> 00:55:43,860 [Uczeń] Więc wszystkie tablice są właściwie tylko wskaźniki. 664 00:55:43,860 --> 00:55:53,630 Istnieje niewielka różnica, kiedy mówię, int x [4] >> [Student] Czy aby utworzyć pamięć? 665 00:55:53,630 --> 00:56:03,320 [Bowden] To zamierza stworzyć 4 wskazówki na stosie, więc 16 bajtów ogólnej. 666 00:56:03,320 --> 00:56:05,700 To będzie tworzyć 16 bajtów na stosie. 667 00:56:05,700 --> 00:56:09,190 x nie jest nigdzie zapisane. 668 00:56:09,190 --> 00:56:13,420 Jest to po prostu symbol myśli początku rzeczy. 669 00:56:13,420 --> 00:56:17,680 Ponieważ zadeklarował tablicę wewnątrz tej funkcji, 670 00:56:17,680 --> 00:56:22,340 co kompilator ma zamiar zrobić to zamienić wszystkie wystąpienia zmiennej x 671 00:56:22,340 --> 00:56:26,400 w którym to się stało, aby wybrać, aby umieścić te 16 bajtów. 672 00:56:26,400 --> 00:56:30,040 Nie można tego zrobić z char * s, ponieważ s jest rzeczywisty wskaźnik. 673 00:56:30,040 --> 00:56:32,380 To jest wolny, aby następnie wskazać na inne rzeczy. 674 00:56:32,380 --> 00:56:36,140 x jest stała. Nie można mieć punkt do innej tablicy. >> [Uczeń] Dobra. 675 00:56:36,140 --> 00:56:43,420 Ale ten pomysł, to indeksowanie, jest taka sama, niezależnie od tego czy jest to tradycyjna tablica 676 00:56:43,420 --> 00:56:48,230 lub jeśli jest to wskaźnik do czegoś lub jeśli jest to wskaźnik do malloced tablicy. 677 00:56:48,230 --> 00:56:59,770 I rzeczywiście, tak jest, że odpowiada również samo. 678 00:56:59,770 --> 00:57:05,440 To właściwie tylko tłumaczy, co jest wewnątrz wsporników i co z uchwytami 679 00:57:05,440 --> 00:57:07,970 dodaje je razem, a dereferences. 680 00:57:07,970 --> 00:57:14,710 Tak jak jest to ważne w * (+ 3 s) lub S [3]. 681 00:57:16,210 --> 00:57:22,090 [Student] Czy masz wskaźniki wskazujące na tablicach 2-wymiarowe? 682 00:57:22,090 --> 00:57:27,380 >> Jest trudniej. Tradycyjnie, nie. 683 00:57:27,380 --> 00:57:34,720 2-wymiarowa tablica jest tylko 1-wymiarowa tablica z jakimś dogodnym składni 684 00:57:34,720 --> 00:57:54,110 ponieważ kiedy mówię int x [3] [3], jest to tak naprawdę tylko 1 tablica z 9 wartości. 685 00:57:55,500 --> 00:58:03,000 I tak, kiedy wskaźnik, kompilator wie, co mam na myśli. 686 00:58:03,000 --> 00:58:13,090 Jeśli powiem, że x [1] [2], to wie, że chcę iść do drugiego rzędu, więc to będzie pominąć pierwszy 3, 687 00:58:13,090 --> 00:58:17,460 i chce drugą rzecz w tym, więc to będzie dostać ten jeden. 688 00:58:17,460 --> 00:58:20,480 Ale to nadal jest tylko jedno-wymiarowej tablicy. 689 00:58:20,480 --> 00:58:23,660 I tak, jeśli chciałem przypisać wskaźnik do tej tablicy, 690 00:58:23,660 --> 00:58:29,770 Chciałbym powiedzieć, int * p = x; 691 00:58:29,770 --> 00:58:33,220 Typu X jest po prostu - 692 00:58:33,220 --> 00:58:38,280 Jest szorstki mówiąc typ x, ponieważ to tylko symbol i nie jest to rzeczywista zmienna, 693 00:58:38,280 --> 00:58:40,140 ale to tylko int *. 694 00:58:40,140 --> 00:58:44,840 x jest tylko wskaźnik na początku tego. >> [Uczeń] Dobra. 695 00:58:44,840 --> 00:58:52,560 I tak nie jest w stanie przejść [1] [2]. 696 00:58:52,560 --> 00:58:58,370 Myślę, że jest specjalna składnia deklarowania wskaźnik, 697 00:58:58,370 --> 00:59:12,480 coś śmieszne jak int (* p [-. coś absolutnie śmieszne Ja nawet nie wiem. 698 00:59:12,480 --> 00:59:17,090 Ale jest składnia deklarowania wskazówek jak z nawiasami i rzeczy. 699 00:59:17,090 --> 00:59:22,960 Nie może nawet na to pozwolić. 700 00:59:22,960 --> 00:59:26,640 Mogę spojrzeć na coś, co chciał mi powiedzieć prawdę. 701 00:59:26,640 --> 00:59:34,160 Ja patrzę na to później, jeśli jest składnia punktu. Ale nigdy nie będzie to widział. 702 00:59:34,160 --> 00:59:39,670 I nawet składnia jest tak archaiczny, że jeśli używasz go, ludzie będą zdumieni. 703 00:59:39,670 --> 00:59:43,540 Tablice wielowymiarowe są dość rzadkie, jak to jest. 704 00:59:43,540 --> 00:59:44,630 Jesteś całkiem dużo - 705 00:59:44,630 --> 00:59:48,490 Cóż, jeśli robisz rzeczy matrycy nie będzie rzadkością, 706 00:59:48,490 --> 00:59:56,730 ale w C masz rzadko zamiar używać tablice wielowymiarowe. 707 00:59:57,630 --> 01:00:00,470 Tak. >> [Uczeń] Powiedzmy, że mają naprawdę długą tablicę. 708 01:00:00,470 --> 01:00:03,900 >> Więc w pamięci wirtualnej wydaje się być wszystko konsekutywne, 709 01:00:03,900 --> 01:00:05,640 jak elementów tuż obok siebie, 710 01:00:05,640 --> 01:00:08,770 a w pamięci fizycznej, byłoby możliwe, że do rozdrabniania się? >> Tak. 711 01:00:08,770 --> 01:00:16,860 Jak działa pamięć wirtualna to tylko oddziela - 712 01:00:19,220 --> 01:00:24,860 Jednostka alokacji jest strona, która ma tendencję do 4 kilobajtów, 713 01:00:24,860 --> 01:00:29,680 i tak, gdy proces mówi, hej, chcę używać tej pamięci, 714 01:00:29,680 --> 01:00:35,970 System operacyjny ma zamiar przeznaczyć to 4 kilobajtów dla tego małego bloku pamięci. 715 01:00:35,970 --> 01:00:39,100 Nawet jeśli używasz tylko jednego małego bajt całego bloku pamięci, 716 01:00:39,100 --> 01:00:42,850 system operacyjny będzie dać mu pełne 4 kilobajtów. 717 01:00:42,850 --> 01:00:49,410 Więc oznacza to, mógłbym - powiedzmy to jest mój stosu. 718 01:00:49,410 --> 01:00:53,180 Ten stos mogą być rozdzielone. Mój stack może być megabajtów i megabajty. 719 01:00:53,180 --> 01:00:55,020 Mój stosu mogą być ogromne. 720 01:00:55,020 --> 01:01:00,220 Ale sam stos musi być podzielona na kilka pojedynczych stron, 721 01:01:00,220 --> 01:01:09,010 które, jeśli przyjrzymy się tutaj powiedzmy, to jest nasz RAM, 722 01:01:09,010 --> 01:01:16,600 jeśli mam 2 gigabajty pamięci RAM, jest to rzeczywista 0 adres jak 0-gie bajcie mojej pamięci RAM, 723 01:01:16,600 --> 01:01:22,210 i jest to 2 gigabajty całą drogę tutaj. 724 01:01:22,210 --> 01:01:27,230 Więc ta strona może odpowiadać tym bloku tutaj. 725 01:01:27,230 --> 01:01:29,400 Ta strona może odpowiadać tym bloku tutaj. 726 01:01:29,400 --> 01:01:31,560 Ten jeden może odpowiadać ten jeden tutaj. 727 01:01:31,560 --> 01:01:35,540 Więc system operacyjny jest wolny przypisać pamięci fizycznej 728 01:01:35,540 --> 01:01:39,320 do każdej indywidualnej strony arbitralnie. 729 01:01:39,320 --> 01:01:46,180 A to oznacza, że ​​jeśli ta granica stanie się plasujące tablicę, 730 01:01:46,180 --> 01:01:50,070 array dzieje się po lewej i prawej stronie tego porządku na stronie, 731 01:01:50,070 --> 01:01:54,460 następnie, że tablica ma być podzielony w pamięci fizycznej. 732 01:01:54,460 --> 01:01:59,280 A następnie po zamknięciu tego programu, gdy proces kończy się 733 01:01:59,280 --> 01:02:05,690 Odwzorowania te uzyskać usunięte i wtedy jest do korzystania z tych małych bloków dla innych rzeczy. 734 01:02:14,730 --> 01:02:17,410 Więcej pytań? 735 01:02:17,410 --> 01:02:19,960 [Uczeń] arytmetyczna wskaźnika. >> Oh yeah. 736 01:02:19,960 --> 01:02:28,410 Struny były łatwiejsze, ale patrząc na coś takiego jak wskazówki, 737 01:02:28,410 --> 01:02:35,000 więc z powrotem do int x [4]; 738 01:02:35,000 --> 01:02:41,810 Czy jest to tablica lub czy jest to wskaźnik do tablicy 4 malloced liczb całkowitych, 739 01:02:41,810 --> 01:02:47,060 to będzie traktowany tak samo. 740 01:02:50,590 --> 01:02:53,340 [Uczeń] Więc tablice są na stercie? 741 01:03:01,400 --> 01:03:05,270 [Bowdena] Tablice nie są na stercie. >> [Uczeń] Oh. 742 01:03:05,270 --> 01:03:08,320 >> [Bowden] macierzy tego typu jest zazwyczaj na stosie 743 01:03:08,320 --> 01:03:12,220 chyba że uznana go na - ignorowanie zmiennych globalnych. Nie należy używać zmiennych globalnych. 744 01:03:12,220 --> 01:03:16,280 Wewnątrz funkcji mówię int x [4]; 745 01:03:16,280 --> 01:03:22,520 To będzie stworzenie 4-całkowitą blokadę na stosie dla tej tablicy. 746 01:03:22,520 --> 01:03:26,960 Ale to malloc (4 * sizeof (int)); ma zamiar iść na stercie. 747 01:03:26,960 --> 01:03:31,870 Ale po tym momencie można użyć X i P w prawie tych samych sposobów, 748 01:03:31,870 --> 01:03:36,140 poza wyjątkami mówiłem o można przypisać p. 749 01:03:36,140 --> 01:03:40,960 Technicznie, ich rozmiary są nieco inne, ale to jest zupełnie nieistotne. 750 01:03:40,960 --> 01:03:43,310 Nigdy właściwie wykorzystywać swoje rozmiary. 751 01:03:48,020 --> 01:03:56,810 P mogę powiedzieć p [3] = 2, lub x [3] = 2; 752 01:03:56,810 --> 01:03:59,680 Można ich używać w dokładnie tych samych metod. 753 01:03:59,680 --> 01:04:01,570 Więc arytmetyczna wskaźnika teraz - Tak. 754 01:04:01,570 --> 01:04:07,390 [Uczeń] Nie musisz zrobić * p jeśli masz konsole? 755 01:04:07,390 --> 01:04:11,720 Wsporniki są niejawne dereference. >> Okay. 756 01:04:11,720 --> 01:04:20,200 Właściwie, także to, co mówisz, ze można dostać tablice wielowymiarowe 757 01:04:20,200 --> 01:05:02,650 ze wskaźnikami, co możesz zrobić, to coś jak, powiedzmy, int ** pp = malloc (sizeof (int *) * 5); 758 01:05:02,650 --> 01:05:06,900 Ja po prostu piszę to wszystko w pierwszej kolejności. 759 01:05:37,880 --> 01:05:41,020 Nie chcę, że jeden. 760 01:05:41,020 --> 01:05:42,550 Okay. 761 01:05:42,550 --> 01:05:48,910 Co ja tutaj jest - To powinno być pp [i]. 762 01:05:48,910 --> 01:05:53,680 Więc pp jest wskaźnik do wskaźnika. 763 01:05:53,680 --> 01:06:02,420 Jesteś mallocing pp zwrócić do tablicy 5 int gwiazd. 764 01:06:02,420 --> 01:06:10,950 Więc w pamięci masz na pp stosu 765 01:06:10,950 --> 01:06:20,150 To będzie punkt do tablicy 5 bloków, które wszystkie są same wskaźniki. 766 01:06:20,150 --> 01:06:28,210 A potem, kiedy malloc tu, I malloc, że każdy z tych poszczególnych wskaźników 767 01:06:28,210 --> 01:06:32,080 powinien wskazywać na osobny blok 4 bajtów na stercie. 768 01:06:32,080 --> 01:06:35,870 Więc to wskazuje na 4 bajtach. 769 01:06:37,940 --> 01:06:40,660 A ten wskazuje na inny 4 bajtów. 770 01:06:40,660 --> 01:06:43,200 >> I wszystkie z nich wskazują na własnych 4 bajtów. 771 01:06:43,200 --> 01:06:49,080 To daje mi sposób prowadzenia wielowymiarowych rzeczy. 772 01:06:49,080 --> 01:06:58,030 Mógłbym powiedzieć, pp [3] [4], ale teraz nie jest to samo, co tablice wielowymiarowe 773 01:06:58,030 --> 01:07:05,390 bo wielowymiarowymi tablicami to tłumaczone [3] [4] w jeden przesunięcie do tablicy x. 774 01:07:05,390 --> 01:07:14,790 To p dereferences, dostęp do trzeciego indeksu, a następnie dereferences że 775 01:07:14,790 --> 01:07:20,790 i odwiedziny - 4 byłyby nieważne - drugi indeks. 776 01:07:24,770 --> 01:07:31,430 Mając na uwadze, kiedy mieliśmy int x [3] [4] przed jako wielowymiarową tablicą 777 01:07:31,430 --> 01:07:35,740 i po dwukrotnym wspornik to naprawdę tylko jeden dereference, 778 01:07:35,740 --> 01:07:40,490 jesteś po jednego wskaźnika, a następnie przesunięcie, 779 01:07:40,490 --> 01:07:42,850 to jest naprawdę 2D referencje. 780 01:07:42,850 --> 01:07:45,840 Możesz śledzić 2 oddzielne wskaźniki. 781 01:07:45,840 --> 01:07:50,420 Więc to również technicznie pozwala mieć tablice wielowymiarowe 782 01:07:50,420 --> 01:07:53,550 gdzie każdy tablica jest różne rozmiary. 783 01:07:53,550 --> 01:07:58,000 Więc myślę, że poszarpane wielowymiarowymi tablicami, jest to, co się nazywa 784 01:07:58,000 --> 01:08:01,870 ponieważ naprawdę pierwszą rzeczą mogą wskazywać na coś, co ma 10 elementów, 785 01:08:01,870 --> 01:08:05,540 Druga sprawa może wskazywać na coś, co ma 100 elementów. 786 01:08:05,540 --> 01:08:10,790 [Student] Czy istnieje ograniczenie liczby wskaźników można mieć 787 01:08:10,790 --> 01:08:14,290 wskazując na inne wskaźniki? No >> 788 01:08:14,290 --> 01:08:17,010 Możesz mieć int p *****. 789 01:08:18,050 --> 01:08:23,760 Powrót do arytmetyki wskazówkach - >> [uczeń] Oh. >> Tak. 790 01:08:23,760 --> 01:08:35,649 [Uczeń] Jeśli mam int *** P, a potem zrobić dereferencji i mówię * p jest równa tej wartości, 791 01:08:35,649 --> 01:08:39,560 Czy jest to tylko zamiar zrobić 1 poziom dereferencji? >> Tak. 792 01:08:39,560 --> 01:08:43,340 Więc jeśli chcesz mieć dostęp do rzeczy, że ostatni wskaźnik jest wskazując na - 793 01:08:43,340 --> 01:08:46,210 Następnie zrobić P ***. >> Okay. 794 01:08:46,210 --> 01:08:54,080 Więc to jest punkty P do 1 bloku, punkty do innego bloku, wskazuje na innego bloku. 795 01:08:54,080 --> 01:09:02,010 Wówczas, jeśli * p = coś innego, to są zmiany tego 796 01:09:02,010 --> 01:09:13,640 Dotychczas wskazać innego bloku. >> Okay. 797 01:09:13,640 --> 01:09:17,649 >> [Bowden] A jeśli były one malloced, to masz teraz pamięć wyciekła 798 01:09:17,649 --> 01:09:20,430 chyba że zdarzy ci się mieć różne odniesienia do tych 799 01:09:20,430 --> 01:09:25,270 skoro nie można dostać się z powrotem do tych z nich, że po prostu wyrzucił. 800 01:09:25,270 --> 01:09:29,550 Arytmetyczna wskaźnika. 801 01:09:29,550 --> 01:09:36,310 int x [4]; zamierza przeznaczyć tablicę 4 liczb 802 01:09:36,310 --> 01:09:40,670 gdzie X będzie wskazywać na początku tablicy. 803 01:09:40,670 --> 01:09:50,420 Więc kiedy mówię coś jak X [1], chcę go do myśli przejść do drugiego całkowitą w tablicy, 804 01:09:50,420 --> 01:09:53,319 które może ta. 805 01:09:53,319 --> 01:10:04,190 Ale tak naprawdę, to 4 bajty do tablicy ponieważ całkowita zajmuje 4 bajty. 806 01:10:04,190 --> 01:10:08,470 Więc przesunięcie 1 naprawdę oznacza przesunięcie 1 807 01:10:08,470 --> 01:10:12,030 razy większe bez względu na rodzaj tablicy jest. 808 01:10:12,030 --> 01:10:17,170 To jest tablica liczb całkowitych, więc wie, zrobić 1 razy rozmiar int gdy chce przesunięcia. 809 01:10:17,170 --> 01:10:25,260 Inna składnia. Pamiętaj, że jest to równoważne * (x + 1); 810 01:10:25,260 --> 01:10:35,250 Kiedy mówię, że wskaźnik + 1, co to jest adres wraca, że ​​wskaźnik jest przechowywanie 811 01:10:35,250 --> 01:10:40,360 plus 1 razy wielkość typu wskaźnika. 812 01:10:40,360 --> 01:10:59,510 Więc jeśli x = OX100, to x + 1 = ox104. 813 01:10:59,510 --> 01:11:19,750 I można nadużywać i powiedzieć coś jak char * c = (char *) x; 814 01:11:19,750 --> 01:11:23,050 a teraz c będzie adres jak x. 815 01:11:23,050 --> 01:11:26,040 c będzie równa OX100, 816 01:11:26,040 --> 01:11:31,490 a c + 1 będzie równe ox101 817 01:11:31,490 --> 01:11:38,030 od arytmetyczna wskaźnika zależy od rodzaju wskaźnika, który jest dodawany do. 818 01:11:38,030 --> 01:11:45,390 Więc c + 1, to wygląda na około, to wskaźnik char, więc to będzie dodać 1 razy rozmiar char, 819 01:11:45,390 --> 01:11:48,110 która zawsze będzie 1, więc masz 101, 820 01:11:48,110 --> 01:11:54,890 mając na uwadze, jeśli mam zrobić X, który również jest nadal 100, x + 1 będzie 104. 821 01:11:56,660 --> 01:12:06,340 [Uczeń] Możesz użyć C + +, w celu poszerzenia swojej wskaźnik przez 1? 822 01:12:06,340 --> 01:12:09,810 Tak, można. 823 01:12:09,810 --> 01:12:16,180 Nie można tego zrobić z powodu x x to tylko symbol, to jest stała, nie można zmienić x. 824 01:12:16,180 --> 01:12:22,610 >> Ale c dzieje po prostu wskaźnik, więc c + + jest całkowicie poprawny i będzie to przyrost o 1. 825 01:12:22,610 --> 01:12:32,440 Jeśli c były po prostu int *, to c + + będzie 104. 826 01:12:32,440 --> 01:12:41,250 + + Czy arytmetyka wskaźnik tak jak c + 1 zrobiłby arytmetyczne wskaźnika. 827 01:12:43,000 --> 01:12:48,870 To jest rzeczywiście, jak wiele rzeczy, takich jak sortowanie korespondencji seryjnej - 828 01:12:49,670 --> 01:12:55,710 Zamiast tworzyć kopie rzeczy, można zamiast tego przekazać - 829 01:12:55,710 --> 01:13:02,400 Jakbym chciał przekazać tę połowę tablicy - niech skasować niektóre to. 830 01:13:04,770 --> 01:13:10,520 Powiedzmy, że chciałem przekazać tę stronę tablicy do funkcji. 831 01:13:10,520 --> 01:13:12,700 Co chciałbym przejść do tej funkcji? 832 01:13:12,700 --> 01:13:17,050 Jeśli zdam x, jestem zdania tego adresu. 833 01:13:17,050 --> 01:13:23,780 Ale chcę, aby przekazać ten konkretny adres. Więc co mam przejść? 834 01:13:23,780 --> 01:13:26,590 [Uczeń] Pointer + 2? 835 01:13:26,590 --> 01:13:29,350 [Bowden] Więc x + 2. Tak. 836 01:13:29,350 --> 01:13:31,620 To będzie ten adres. 837 01:13:31,620 --> 01:13:42,810 Będziesz także bardzo często postrzegają ją jako x [2], a następnie adres to. 838 01:13:42,810 --> 01:13:47,850 Więc musisz mieć adres, bo uchwyt jest niejawna dereference. 839 01:13:47,850 --> 01:13:53,250 x [2] odnosi się do wartości, która jest w tym polu, a potem chcesz, aby adres tej skrzynki, 840 01:13:53,250 --> 01:13:56,850 tak mówisz & x [2]. 841 01:13:56,850 --> 01:14:02,880 Więc to jest jak coś w rodzaju łączenia, w której chcesz przekazać pół listę do czegoś 842 01:14:02,880 --> 01:14:08,790 naprawdę tylko przejść & x [2], a teraz aż wywołanie rekurencyjne jest zaniepokojony, 843 01:14:08,790 --> 01:14:12,510 moja nowa tablica zaczyna się tam. 844 01:14:12,510 --> 01:14:15,130 Ostatnie pytania minut. 845 01:14:15,130 --> 01:14:20,050 [Uczeń] Jeśli nie położymy ampersand lub - co to się nazywa? >> Star? 846 01:14:20,050 --> 01:14:23,200 [Uczeń] Star. >> Technicznie, operator dereference, ale - >> [uczeń] dereference. 847 01:14:23,200 --> 01:14:29,310 >> Jeśli nie położymy gwiazdę lub handlowego i, co się stanie, jeśli po prostu powiedzieć, y = x, x jest wskaźnik? 848 01:14:29,310 --> 01:14:34,620 Co to jest typ Y? >> [Uczeń] Powiem tylko, że to wskaźnik 2. 849 01:14:34,620 --> 01:14:38,270 Więc jeśli tylko powiedzieć, y = x, x, a teraz punkt y do tej samej rzeczy. >> [Uczeń] Punkt do tej samej rzeczy. 850 01:14:38,270 --> 01:14:45,180 A jeśli x jest int wskaźnik? >> By narzekać, ponieważ nie można przypisać wskaźniki. 851 01:14:45,180 --> 01:14:46,540 [Uczeń] Dobra. 852 01:14:46,540 --> 01:14:51,860 Pamiętaj, że wskaźniki, choć zwracamy je jako strzałki, 853 01:14:51,860 --> 01:15:02,010 naprawdę wszystko, sklep - int * x - naprawdę wszystko x jest przechowywanie jest czymś OX100, 854 01:15:02,010 --> 01:15:06,490 które się do reprezentowania w bloku wskazując przechowywane w 100. 855 01:15:06,490 --> 01:15:19,660 Więc kiedy mówię, int * y = x; Ja tylko kopiowanie OX100 w y, 856 01:15:19,660 --> 01:15:24,630 które po prostu będzie reprezentować jako y, także wskazując OX100. 857 01:15:24,630 --> 01:15:39,810 A jeśli powiem, int i = (int) x; następnie i będzie przechowywać, co jest wartością OX100 858 01:15:39,810 --> 01:15:45,100 wewnątrz niego, ale teraz to będzie interpretowane jako liczba całkowita zamiast wskaźnika. 859 01:15:45,100 --> 01:15:49,310 Ale trzeba do obsady albo będzie narzekać. 860 01:15:49,310 --> 01:15:53,300 [Uczeń] Więc to znaczy oddać - 861 01:15:53,300 --> 01:16:00,290 Czy to będzie odlewania int int x lub y odlew? 862 01:16:00,290 --> 01:16:03,700 [Bowden] Co? 863 01:16:03,700 --> 01:16:07,690 [Uczeń] Dobra. Po tych nawiasach jest tam będzie x lub aj tam? 864 01:16:07,690 --> 01:16:11,500 >> [Bowden] Albo. X i Y są równoważne. >> [Uczeń] Dobra. 865 01:16:11,500 --> 01:16:14,390 Bo są oba wskaźniki. >> Tak. 866 01:16:14,390 --> 01:16:21,050 [Uczeń] Tak byłoby przechowywać szesnastkową 100 w całkowitej formie? >> [Bowden] Tak. 867 01:16:21,050 --> 01:16:23,620 Ale wartość cokolwiek to wskazuje. 868 01:16:23,620 --> 01:16:29,940 [Bowden] Tak. >> [Uczeń] Więc po prostu adres w postaci liczby całkowitej. Okay. 869 01:16:29,940 --> 01:16:34,720 [Bowden] Jeśli chciał jakiegoś dziwacznego powodu 870 01:16:34,720 --> 01:16:38,900 można zająć się wyłącznie wskaźniki i nigdy do czynienia z liczbami całkowitymi 871 01:16:38,900 --> 01:16:49,240 i po prostu być jak int * x = 0. 872 01:16:49,240 --> 01:16:53,000 Wtedy będziesz się naprawdę pomylić raz arytmetyka wskaźnik zaczyna dzieje. 873 01:16:53,000 --> 01:16:56,570 Więc numery ich przechowywania są bezsensowne. 874 01:16:56,570 --> 01:16:58,940 To jest po prostu, jak skończy się ich interpretacji. 875 01:16:58,940 --> 01:17:02,920 Więc jestem wolny skopiować OX100 z int * na int, 876 01:17:02,920 --> 01:17:07,790 i jestem wolny, aby przypisać - Jeste prawdopodobnie będzie się krzyknął na nie Casting - 877 01:17:07,790 --> 01:17:18,160 Jestem wolny, aby przypisać coś (int *) ox1234 w ten arbitralny * int. 878 01:17:18,160 --> 01:17:25,480 Więc ox123 jest tak samo ważne jak to jest adres pamięci & y. 879 01:17:25,480 --> 01:17:32,060 & Y dzieje się powrócić, że coś jest bardzo dużo ox123. 880 01:17:32,060 --> 01:17:35,430 [Student] Czy tak jest naprawdę fajny sposób, aby przejść od szesnastkowy do postaci dziesiętnej, 881 01:17:35,430 --> 01:17:39,230 podoba, jeśli masz wskaźnik i używasz go jako int? 882 01:17:39,230 --> 01:17:44,860 [Bowden] Można naprawdę tylko drukowanie za pomocą tak jak printf. 883 01:17:44,860 --> 01:17:50,300 Powiedzmy, że mam int y = 100. 884 01:17:50,300 --> 01:18:02,700 Więc printf (% d \ n - jak powinien już wiesz - drukuj, że jak Integer, x%. 885 01:18:02,700 --> 01:18:05,190 My po prostu wydrukować go w postaci szesnastkowej. 886 01:18:05,190 --> 01:18:10,760 Tak więc wskaźnik nie jest przechowywana jako szesnastkowy 887 01:18:10,760 --> 01:18:12,960 i całkowita nie jest przechowywany jako przecinku. 888 01:18:12,960 --> 01:18:14,700 Wszystko jest przechowywane jako binarny. 889 01:18:14,700 --> 01:18:17,950 To jest po prostu, że mamy tendencję, aby pokazać, jak wskaźniki szesnastkowo 890 01:18:17,950 --> 01:18:23,260 ponieważ uważamy, że rzeczy w tych blokach 4-bajtowych, 891 01:18:23,260 --> 01:18:25,390 i adresy pamięci wydają się być znajome. 892 01:18:25,390 --> 01:18:28,890 Jesteśmy jak, jeśli zaczyna się od bf, to dzieje się na stosie. 893 01:18:28,890 --> 01:18:35,560 Więc jest to tylko nasza interpretacja wskaźników jak szesnastkowo. 894 01:18:35,560 --> 01:18:39,200 Okay. Jakieś ostatnie pytania? 895 01:18:39,200 --> 01:18:41,700 >> Będę tu na trochę po jeśli masz coś innego. 896 01:18:41,700 --> 01:18:46,070 I to jest koniec tego. 897 01:18:46,070 --> 01:18:48,360 >> [Uczeń] Yay! [Oklaski] 898 01:18:51,440 --> 01:18:53,000 >> [CS50.TV]