1 00:00:00,000 --> 00:00:02,500 [Powered by Google Translate] [Rozdział 5 - bardziej komfortowe] 2 00:00:02,500 --> 00:00:04,690 [Rob Bowden - Harvard University] 3 00:00:04,690 --> 00:00:07,250 [To jest CS50. - CS50.TV] 4 00:00:08,990 --> 00:00:14,250 >> Jak powiedziałem w moim e-mail, istnieje wiele rzeczy, których można używać 5 00:00:14,250 --> 00:00:17,060 inne niż urządzenia faktycznie zrobić zestawy problemów. 6 00:00:17,060 --> 00:00:19,910 Zalecamy to zrobić w urządzeniu, tylko dlatego, możemy łatwiej pomóc 7 00:00:19,910 --> 00:00:22,070 i wiemy, jak to wszystko będzie działać. 8 00:00:22,070 --> 00:00:26,950 Ale jako jeden z przykładów, gdzie można robić rzeczy, jeśli, powiedzmy, że nie mają dostępu 9 00:00:26,950 --> 00:00:31,570 do urządzenia lub chcesz pracować w podziemiach Centrum Nauki - 10 00:00:31,570 --> 00:00:33,090 które w rzeczywistości mają urządzenia również - 11 00:00:33,090 --> 00:00:35,150 jeśli chcesz pracować w dowolnym miejscu. 12 00:00:35,150 --> 00:00:42,370 Jednym z przykładów jest widziałeś / słyszałeś SSH? 13 00:00:44,380 --> 00:00:47,780 SSH jest w zasadzie tak, jak połączyć się z czegoś. 14 00:00:47,780 --> 00:00:51,340 Właściwie teraz jestem SSHed do urządzenia. 15 00:00:51,340 --> 00:00:54,290 Nigdy nie pracować bezpośrednio w urządzeniu. 16 00:00:55,930 --> 00:01:01,060 Oto urządzenie, i jeśli spojrzeć na dół zobaczyć tego adresu IP. 17 00:01:01,060 --> 00:01:03,650 Nigdy nie pracować w samego urządzenia; 18 00:01:03,650 --> 00:01:08,840 I zawsze przyjść do iTerm2 oknie terminala / oknie. 19 00:01:08,840 --> 00:01:15,910 Możesz SSH do tego adresu IP, ssh jharvard@192.168.129.128. 20 00:01:15,910 --> 00:01:20,390 Pamiętam ten numer bardzo łatwo, bo to taki ładny wzór. 21 00:01:20,390 --> 00:01:24,920 Ale że poprosi mnie o hasło, a teraz jestem w urządzeniu. 22 00:01:24,920 --> 00:01:33,060 Zasadniczo, w tym momencie, jeśli terminal otwarty wewnątrz samego urządzenia, 23 00:01:33,060 --> 00:01:36,350 ten interfejs, jednak chcesz go używać, jest dokładnie taka sama 24 00:01:36,350 --> 00:01:40,010 jako interfejsu używam tutaj ale teraz SSHed. 25 00:01:42,240 --> 00:01:44,920 Nie masz do SSH do urządzenia. 26 00:01:44,920 --> 00:01:52,360 Przykładem innego miejsca, w którym mógłby ssh to jestem pewien, masz domyślnie - 27 00:01:52,360 --> 00:01:55,020 Oh. Większe. 28 00:01:55,020 --> 00:02:01,130 Każdy z was powinien mieć przez FAS domyślnych kont na serwerach FAS. 29 00:02:01,130 --> 00:02:06,840 Dla mnie, bym SSH rbowden@nice.fas.harvard.edu. 30 00:02:06,840 --> 00:02:11,610 To będzie prosić, że po raz pierwszy, i że tak. 31 00:02:11,610 --> 00:02:15,840 Moje hasło jest tylko będzie moje hasło FAS. 32 00:02:15,840 --> 00:02:22,650 I tak teraz, jestem SSHed do miłych serwerach, i mogę robić co zechcę tutaj. 33 00:02:22,650 --> 00:02:28,560 Wiele klas może podjąć, jak 124, będą musieli przesyłać rzeczy do tego miejsca 34 00:02:28,560 --> 00:02:30,950 faktycznie przesłać zestawy problemów. 35 00:02:30,950 --> 00:02:34,100 Ale mówisz, że nie masz dostępu do urządzenia. 36 00:02:34,100 --> 00:02:37,910 Potem możesz robić rzeczy, jak tu będzie to powiedzieć - 37 00:02:37,910 --> 00:02:42,160 To jest po prostu nasza sekcja pytań. 38 00:02:42,160 --> 00:02:45,070 Będzie prosić, aby to zrobić w urządzeniu. 39 00:02:45,070 --> 00:02:47,790 Zamiast ja po prostu zrobić to na serwerze. 40 00:02:47,790 --> 00:02:50,560 Idę do rozpakowania tego. 41 00:02:50,560 --> 00:02:55,670 Problem będzie, że jesteś przyzwyczajony do korzystania coś gedit 42 00:02:55,670 --> 00:02:58,160 lub cokolwiek wewnątrz urządzenia. 43 00:02:58,160 --> 00:03:01,830 Nie będziemy mieć, że na serwerze FAS. 44 00:03:01,830 --> 00:03:04,110 To wszystko tylko będzie to tekstowy interfejs. 45 00:03:04,110 --> 00:03:09,180 Więc można albo jedno, spróbuj dowiedzieć się edytor tekstu, że mamy. 46 00:03:09,180 --> 00:03:12,130 Mają Nano. 47 00:03:12,130 --> 00:03:14,990 Nano jest zazwyczaj bardzo proste w użyciu. 48 00:03:14,990 --> 00:03:19,470 Możesz użyć strzałek i wpisz normalnie. 49 00:03:19,470 --> 00:03:21,250 Więc to nie jest trudne. 50 00:03:21,250 --> 00:03:24,720 Jeśli chcesz uzyskać naprawdę fantazyjne można użyć Emacsa, 51 00:03:24,720 --> 00:03:29,850 które prawdopodobnie nie powinno otworzyły bo nawet nie wiem jak zamknąć Emacsa. 52 00:03:29,850 --> 00:03:32,760 Sterowanie X, Control C? Tak. 53 00:03:32,760 --> 00:03:35,310 Albo użyć Vima, która jest ich używam. 54 00:03:35,310 --> 00:03:37,800 I tak są to opcje. 55 00:03:37,800 --> 00:03:43,830 Jeśli nie chcesz tego zrobić, możesz także, jeśli spojrzeć na manual.cs50.net-- 56 00:03:43,830 --> 00:03:45,410 Oh. 57 00:03:45,410 --> 00:03:49,920 Na PC można SSH przy użyciu PuTTY, 58 00:03:49,920 --> 00:03:51,940 które będziesz musiał pobrać oddzielnie. 59 00:03:51,940 --> 00:03:55,460 Na komputerze Mac, można po prostu przez Terminal USE lub możesz pobrać iTerm2, 60 00:03:55,460 --> 00:03:58,490 która jest jak miły, Terminal fantazji. 61 00:03:58,490 --> 00:04:03,780 Jeśli pójdziesz do manual.cs50.net zobaczysz link do Notepad + +, 62 00:04:03,780 --> 00:04:07,120 czyli to, co można używać na komputerze. 63 00:04:07,120 --> 00:04:13,340 Pozwala SFTP z Notepad + +, który jest w zasadzie SSH. 64 00:04:13,340 --> 00:04:17,750 Co ta pozwoli Ci zrobić to edytować pliki lokalnie, 65 00:04:17,750 --> 00:04:20,670 , a następnie, gdy chcesz je zapisać, to zaoszczędzić do nice.fas, 66 00:04:20,670 --> 00:04:23,670 gdzie możesz je uruchomić. 67 00:04:23,670 --> 00:04:26,880 A odpowiednik na Mac będzie TextWrangler. 68 00:04:26,880 --> 00:04:28,760 Więc pozwala zrobić to samo. 69 00:04:28,760 --> 00:04:32,800 Pozwala edytować pliki lokalnie i zapisać je do nice.fas, 70 00:04:32,800 --> 00:04:35,730 gdzie możesz je uruchomić. 71 00:04:35,730 --> 00:04:40,400 Więc jeśli kiedykolwiek zatrzymany bez urządzenia, masz te opcje 72 00:04:40,400 --> 00:04:44,230 aby nadal robić swoje zestawy problemów. 73 00:04:44,230 --> 00:04:48,250 Jeden problem ma być to, że nie będziemy mieć CS50 biblioteki 74 00:04:48,250 --> 00:04:51,580 bo nice.fas domyślnie nie mieć. 75 00:04:51,580 --> 00:04:55,970 Możesz pobrać CS50 biblioteki - 76 00:04:55,970 --> 00:04:58,470 Nie sądzę, że muszę, że w tym momencie. 77 00:04:58,470 --> 00:05:03,270 Możesz pobrać CS50 biblioteki i skopiować go do nice.fas, 78 00:05:03,270 --> 00:05:07,450 lub Myślę, że w tym momencie nie używamy go już tak. 79 00:05:07,450 --> 00:05:12,720 Albo jeśli to zrobimy, można na razie zastąpić go 80 00:05:12,720 --> 00:05:18,480 implementacje funkcji w CS50 biblioteki i tak. 81 00:05:18,480 --> 00:05:21,370 Tak, że nie może być o wiele ograniczenia. 82 00:05:21,370 --> 00:05:23,710 I to jest to. 83 00:05:26,460 --> 00:05:29,820 >> Wrócę do urządzenia teraz, zrobimy wszystko, co w urządzeniu. 84 00:05:29,820 --> 00:05:37,510 Patrząc na naszej sekcji pytań, na początku, jak powiedziałem w moim e-mail, 85 00:05:37,510 --> 00:05:43,620 Musimy porozmawiać o jednym krótkim Miałeś oglądać. 86 00:05:43,620 --> 00:05:51,980 Mamy przekierowanie i rur i te trzy pytania. 87 00:05:51,980 --> 00:05:56,070 >> Do których nie działa jak strumień printf pisać domyślnie? 88 00:05:56,070 --> 00:05:59,130 Więc stream. Co to jest stream? 89 00:06:06,520 --> 00:06:15,100 Strumień jest w zasadzie jak to tylko niektóre - 90 00:06:15,100 --> 00:06:21,450 To nie jest nawet źródłem 1s i 0s. 91 00:06:21,450 --> 00:06:24,920 Strumień to prosząc o to standardowe wyjście. 92 00:06:24,920 --> 00:06:27,250 I tak średnia obecnie jest strumień, który podczas pisania do niego, 93 00:06:27,250 --> 00:06:30,940 pojawia się na ekranie. 94 00:06:30,940 --> 00:06:36,860 Standardowe wyjście, przez strumień, oznacza to po prostu napisać 1s i 0s do niego, 95 00:06:36,860 --> 00:06:40,220 , a drugi koniec z standardowej się po prostu z tego strumienia odczytuje. 96 00:06:40,220 --> 00:06:43,540 To jest po prostu ciąg 1s i 0s. 97 00:06:43,540 --> 00:06:45,570 Możesz napisać do strumieni lub możesz przeczytać ze strumieni 98 00:06:45,570 --> 00:06:47,950 w zależności od tego, co faktycznie jest strumień. 99 00:06:47,950 --> 00:06:52,800 Pozostałe dwa strumienie domyślne to standardowe i błąd standardowy. 100 00:06:52,800 --> 00:06:57,540 Standardem jest, gdy robisz getString, to czeka na ciebie, aby rzeczy wejściowego. 101 00:06:57,540 --> 00:07:01,570 Tak więc czekam na Ciebie, to faktycznie czeka na standardzie w, 102 00:07:01,570 --> 00:07:04,880 co jest naprawdę to, co dostajesz po wpisaniu na klawiaturze. 103 00:07:04,880 --> 00:07:07,530 Piszesz w standardzie w. 104 00:07:07,530 --> 00:07:10,050 Błąd standardowy jest w zasadzie odpowiednikiem poza standardowym 105 00:07:10,050 --> 00:07:13,280 ale to, że specjalizuje się w przypadku drukowania na standardowym wyjściu błędów, 106 00:07:13,280 --> 00:07:16,770 masz się drukować tylko komunikaty o błędach, które 107 00:07:16,770 --> 00:07:20,200 więc można odróżnić zwykłe wiadomości wyświetlane na ekranie 108 00:07:20,200 --> 00:07:24,560 wobec komunikatów o błędach, w zależności od tego, czy poszedł do wyczerpania standardowego lub błędu standardowego. 109 00:07:24,560 --> 00:07:28,660 Pliki. 110 00:07:28,660 --> 00:07:32,440 Standardowe wyjście, standard, i standardowy błąd to tylko specjalne strumienie, 111 00:07:32,440 --> 00:07:36,810 ale tak naprawdę każdy plik, gdy użytkownik otworzy plik, staje się strumień bajtów 112 00:07:36,810 --> 00:07:40,740 gdzie można po prostu odczytać z tego strumienia. 113 00:07:40,740 --> 00:07:47,770 Ty, w przeważającej części, można po prostu myśleć o pliku jako strumień bajtów. 114 00:07:47,770 --> 00:07:51,190 Więc co oni strumienie zapisu domyślnie? Standardowe wyjście. 115 00:07:51,190 --> 00:07:56,980 >> Jaka jest różnica pomiędzy> i >>? 116 00:07:58,140 --> 00:08:03,710 Czy ktoś obejrzeć film wcześniej? Okay. 117 00:08:03,710 --> 00:08:10,960 > Będzie jak przekierować do plików, 118 00:08:10,960 --> 00:08:15,240 i >> zamierza także przekierować wyjście do plików, 119 00:08:15,240 --> 00:08:17,820 ale to zamiast zamiar dodać do pliku. 120 00:08:17,820 --> 00:08:23,430 Na przykład, powiedzmy, że zdarza mi się mieć dict tu, 121 00:08:23,430 --> 00:08:27,020 i tylko rzeczy wewnątrz dict jest kot, kot, pies, ryba, pies. 122 00:08:27,020 --> 00:08:31,530 Jedno polecenie, że trzeba w wierszu poleceń jest kot, 123 00:08:31,530 --> 00:08:34,539 który jest właśnie do druku, co jest w pliku. 124 00:08:34,539 --> 00:08:40,679 Więc kiedy mówię dict kota, to będzie drukować kota, kot, pies, ryby, psa. To wszystko, kot robi. 125 00:08:40,679 --> 00:08:46,280 Oznacza to, że drukowane na standardowe wyjście kot, kot, pies, ryby, psa. 126 00:08:46,280 --> 00:08:53,240 Jeśli zamiast tego chcesz przekierowanie do pliku, można użyć> i przekierować ją do tego, co plik. 127 00:08:53,240 --> 00:08:56,460 Zadzwonię do pliku plik. 128 00:08:56,460 --> 00:09:00,320 Tak więc jeśli ls, zobaczę mam nowy plik o nazwie pliku. 129 00:09:00,320 --> 00:09:05,700 I jeśli go otworzyć, to będzie mieć dokładnie to, co kot umieścić w wierszu polecenia. 130 00:09:05,700 --> 00:09:11,040 Więc teraz, jeśli to zrobię to jeszcze raz, a potem to się przekierować wyjście do pliku, 131 00:09:11,040 --> 00:09:13,930 i mam zamiar mieć dokładnie taki sam rzecz. 132 00:09:13,930 --> 00:09:17,910 Więc technicznie, całkowicie zagłuszył to, co mieliśmy. 133 00:09:17,910 --> 00:09:22,970 I zobaczymy, jeśli zmienię dict, wyjąłem psa. 134 00:09:22,970 --> 00:09:29,980 Teraz jeśli kot dict do pliku ponownie, będziemy mieć nową wersję z psem usunięte. 135 00:09:29,980 --> 00:09:32,400 Więc to, że całkowicie przesłania go. 136 00:09:32,400 --> 00:09:36,640 Zamiast tego, jeśli używamy >>, to będzie dołączyć plik. 137 00:09:36,640 --> 00:09:40,860 Teraz, otwierania pliku, widzimy, mamy tylko samo wydrukowane dwukrotnie 138 00:09:40,860 --> 00:09:44,920 dlatego, że był tam kiedyś, to dołączone do oryginału. 139 00:09:44,920 --> 00:09:48,130 Więc to> i >> zrobić. 140 00:09:48,130 --> 00:09:50,580 Czy następny zapytać - To nie o to zapytać. 141 00:09:50,580 --> 00:09:59,050 >> Druga, że ​​mamy jest <, które jeśli> przekierowuje standardowe wyjście, 142 00:09:59,050 --> 00:10:01,970 00:10:12,050 Zobaczymy, czy mamy przykład. 144 00:10:14,750 --> 00:10:16,930 Mogę napisać jeden bardzo szybko. 145 00:10:17,870 --> 00:10:25,700 Weźmy dowolny plik, hello.c. 146 00:10:56,060 --> 00:10:59,070 Stosunkowo prosty plik. 147 00:10:59,070 --> 00:11:03,570 Ja tylko się łańcuch, a następnie drukuje "Hello", co ciąg Właśnie weszła było. 148 00:11:03,570 --> 00:11:07,990 Tak aby przywitać i potem. / Hello. 149 00:11:07,990 --> 00:11:10,720 Teraz to co skłoniło mnie, aby wprowadzić coś, 150 00:11:10,720 --> 00:11:15,070 co oznacza, że ​​czeka na rzeczy, które będą wprowadzane do standardu w. 151 00:11:15,070 --> 00:11:20,450 Więc co chcę wprowadzić do standardu w. Po prostu powiedzieć Witaj, Rob! 152 00:11:20,450 --> 00:11:23,310 Wtedy to jest drukowane na standardowe wyjście Witaj, Rob! 153 00:11:23,310 --> 00:11:28,860 Jeśli zrobić. / Hello, a następnie przekierować, 154 00:11:30,740 --> 00:11:34,310 Na razie można tylko przekierowanie z pliku. 155 00:11:34,310 --> 00:11:41,720 Więc jeśli mogę umieścić w jakimś pliku, txt, i umieścić Rob 156 00:11:41,720 --> 00:11:52,300 jeśli uruchomię witam a następnie przekierować do pliku txt. / hello, to się przywitać, Rob! natychmiast. 157 00:11:52,300 --> 00:11:57,160 Gdy po raz pierwszy trafia do getString i czeka na standardzie w, 158 00:11:57,160 --> 00:12:01,730 standard nie jest już czeka na klawiaturze, aby uzyskać dla danych wprowadzonych. 159 00:12:01,730 --> 00:12:05,980 Zamiast tego, mamy przekierowany standard odczytu z pliku txt. 160 00:12:05,980 --> 00:12:10,290 I tak się dzieje do odczytu z pliku txt, który jest po prostu linia Rob, 161 00:12:10,290 --> 00:12:13,380 a potem to się wydrukować Witaj, Rob! 162 00:12:13,380 --> 00:12:18,180 A jeśli chcę, mogę również zrobić. / Hello 00:12:21,500 a średnia się, że to druk, który jest Hello, Rob!, 164 00:12:21,500 --> 00:12:24,700 Można przekierować, że do własnego pliku. 165 00:12:24,700 --> 00:12:29,790 Ja po prostu zadzwonić do pliku hello - no, nie powiem, bo to plik wykonywalny - txt2. 166 00:12:29,790 --> 00:12:40,150 Teraz txt2 będzie miał wyjście. / Hello 00:12:43,520 >> Questions? 168 00:12:45,900 --> 00:12:49,090 >> Okay. Więc tutaj mamy rurociąg. 169 00:12:49,090 --> 00:12:53,510 Rury są ostatnie urządzenie z przekierowania. 170 00:12:53,510 --> 00:12:58,750 >> Oh. Chyba jedna jednostka przekierowania jest, jeśli zamiast> zrobić 2> 171 00:12:58,750 --> 00:13:01,070 który jest przekierowanie standardowego błędu. 172 00:13:01,070 --> 00:13:06,280 Więc jeśli coś się do błędu standardowego, to nie byłoby się położyć do txt2. 173 00:13:06,280 --> 00:13:12,480 Zauważmy jednak, jeśli mam zrobić 2>, a następnie to nadal drukowanie Witaj, Rob! do linii poleceń 174 00:13:12,480 --> 00:13:18,600 bo jestem tylko przekierowanie standardowego błędu, nie jestem przekierowanie standardu zewnątrz. 175 00:13:18,600 --> 00:13:22,210 Standardowy błąd i obecnie standardem są różne. 176 00:13:24,210 --> 00:13:27,080 Jeśli chciał faktycznie napisać do błędu standardowego, 177 00:13:27,080 --> 00:13:35,080 wtedy będę mógł zmienić się fprintf na stderr. 178 00:13:35,080 --> 00:13:37,850 Więc printf, domyślnie drukuje na wyjście standardowe. 179 00:13:37,850 --> 00:13:41,720 Jeśli chcę wydrukować do błędu standardowego ręcznie, potem użyć fprintf 180 00:13:41,720 --> 00:13:45,010 i określić, co chcę drukować. 181 00:13:45,010 --> 00:13:49,720 Jeżeli zamiast tego zrobiłem fprintf stdout, to jest to w zasadzie odpowiednikiem printf. 182 00:13:49,720 --> 00:13:55,530 Ale fprintf do błędu standardowego. 183 00:13:57,790 --> 00:14:03,650 Więc teraz, jeśli mam przekierować to do txt2, Hello, Rob! wciąż się drukowane w linii poleceń 184 00:14:03,650 --> 00:14:08,270 ponieważ wychodzi na standardowym błąd i jestem tylko przekierowuje standardowe wyjście. 185 00:14:08,270 --> 00:14:16,420 Jeśli teraz przekierować standardowy błąd, teraz nie wydrukowany i txt2 będzie Witaj, Rob! 186 00:14:16,420 --> 00:14:21,910 Więc teraz, możesz drukować swoje rzeczywiste błędy błędu standardowego 187 00:14:21,910 --> 00:14:24,720 i drukować regularne komunikaty out standardowe. 188 00:14:24,720 --> 00:14:31,420 I tak po uruchomieniu programu, można uruchomić ją. / Hello tego typu z 2> 189 00:14:31,420 --> 00:14:33,800 tak, że program będzie działać normalnie, 190 00:14:33,800 --> 00:14:38,400 ale komunikaty o błędach, które cię mogą sprawdzić później w dzienniku błędów, 191 00:14:38,400 --> 00:14:44,500 więc błędów, a następnie szukać później i plik błędy nie będą miały żadnych błędów, które się wydarzyły. 192 00:14:45,200 --> 00:14:47,540 >> Questions? 193 00:14:47,540 --> 00:14:58,070 >> Ostatnia jest pipe, które można myśleć jak biorąc standard się z jednego polecenia 194 00:14:58,070 --> 00:15:01,210 i co to standard w następnej komendy. 195 00:15:01,210 --> 00:15:05,570 Przykładem jest tu echo jest rzeczą wiersza poleceń 196 00:15:05,570 --> 00:15:11,840 , który jest po prostu będzie echo cokolwiek umieścić jako argumentu. I nie będzie umieścić cudzysłów. 197 00:15:11,840 --> 00:15:16,150 Echo bla, bla, bla, jest właśnie do druku bla, bla, bla. 198 00:15:16,150 --> 00:15:20,600 Wcześniej, kiedy powiedział, że musiał włożyć Roba do pliku txt 199 00:15:20,600 --> 00:15:28,830 bo mogę tylko przekierowanie plików txt, zamiast / if echo Roba 200 00:15:28,830 --> 00:15:35,520 a następnie go do rury. / hello, że zrobi ten sam rodzaj rzeczy. 201 00:15:35,520 --> 00:15:39,160 To trwa wyjście tego polecenia, echo Rob, 202 00:15:39,160 --> 00:15:43,610 i używanie go jako wejście do. / hello. 203 00:15:44,790 --> 00:15:49,560 Można myśleć o tym jako pierwszy przekierowanie echa Roba do pliku 204 00:15:49,560 --> 00:15:54,160 a następnie wprowadzić do. / hello tym pliku, który właśnie wyprowadzać. 205 00:15:54,160 --> 00:15:57,850 Ale to wymaga tymczasowego pliku z obrazem. 206 00:16:01,890 --> 00:16:04,460 >> Pytania na temat tego? 207 00:16:04,460 --> 00:16:07,150 >> Następne pytanie będzie dotyczyć tego. 208 00:16:07,150 --> 00:16:15,310 Co rurociąg można użyć, aby znaleźć liczbę unikatowych nazw w pliku o nazwie names.txt? 209 00:16:15,310 --> 00:16:24,160 Polecenia zamierzamy użyć tutaj są wyjątkowe, tak uniq, a następnie wc. 210 00:16:24,160 --> 00:16:28,840 Możesz zrobić uniq mężczyzna rzeczywiście patrzeć na to co, że nie, 211 00:16:28,840 --> 00:16:34,840 i to tylko będzie filtrować sąsiadujące pasujące linie z wejścia. 212 00:16:34,840 --> 00:16:40,690 I człowiek wc będzie wydrukować znak nowej linii, słów i bajtów liczy się dla każdego pliku. 213 00:16:40,690 --> 00:16:43,760 I ostatni zamierzamy użyć jest sortowanie, 214 00:16:43,760 --> 00:16:47,410 który będzie po prostu posortować wiersze pliku txt. 215 00:16:47,410 --> 00:16:58,080 Jeśli zrobię jakiś plik txt, names.txt, i to jest Rob, Tommy, Joseph, Tommy, Joseph, RJ, Rob, 216 00:16:58,080 --> 00:17:03,910 co chcę zrobić tutaj jest znaleźć liczbę unikatowych nazw w tym pliku. 217 00:17:03,910 --> 00:17:08,750 Więc co należy odpowiedź? >> [Uczeń] 4. >> Tak. 218 00:17:08,750 --> 00:17:13,780 Powinno być 4 od Rob, Tommy, Józefa, RJ to jedyne unikalne nazwy w tym pliku. 219 00:17:13,780 --> 00:17:20,180 Pierwszy krok, jeśli po prostu liczą na names.txt słowo, 220 00:17:20,180 --> 00:17:24,290 To jest rzeczywiście mówi mi wszystko. 221 00:17:24,290 --> 00:17:32,560 To jest rzeczywiście druk - Zobaczmy, man wc - newlines, słowa i liczyć bajt. 222 00:17:32,560 --> 00:17:38,270 Gdybym tylko o linii, to może po prostu zrobić wc-l names.txt. 223 00:17:41,730 --> 00:17:44,300 Więc to jest etap 1. 224 00:17:44,300 --> 00:17:50,510 Ale ja nie chcę wc-l names.txt ponieważ names.txt tylko zawiera wszystkie nazwiska, 225 00:17:50,510 --> 00:17:54,170 i chcę, aby odfiltrować nie-niepowtarzalne. 226 00:17:54,170 --> 00:18:01,200 Więc jeśli ja names.txt uniq, że nie za bardzo da mi to, co chcę 227 00:18:01,200 --> 00:18:03,760 ponieważ zduplikowane nazwy są nadal. 228 00:18:03,760 --> 00:18:07,690 Dlaczego tak jest? Dlaczego nie uniq robić to, co chcę? 229 00:18:07,690 --> 00:18:10,500 [Uczeń] duplikaty nie są [niesłyszalne] >> Tak. 230 00:18:10,500 --> 00:18:16,370 Zapamiętaj na stronie man uniq mówi filtr sąsiadujące pasujące linie. 231 00:18:16,370 --> 00:18:19,680 Oni nie są w sąsiedztwie, więc nie będzie filtrować je. 232 00:18:19,680 --> 00:18:31,100 Jeśli sortować je najpierw names.txt sort będzie umieścić wszystkie zduplikowane linie razem. 233 00:18:31,100 --> 00:18:34,450 Więc teraz names.txt sort jest. 234 00:18:34,450 --> 00:18:40,550 Mam zamiar użyć, że wejście do uniq, co jest | uniq. 235 00:18:40,550 --> 00:18:43,390 To daje mi Józefa, RJ, Rob, Tommy, 236 00:18:43,390 --> 00:18:49,260 i chcę, aby użyć jej jako wejście do wc-l, 237 00:18:49,260 --> 00:18:52,740 co da mi 4. 238 00:18:52,740 --> 00:18:56,930 Jak tu jest napisane, co rurociąg można użyć? 239 00:18:56,930 --> 00:19:01,390 Można zrobić wiele rzeczy, jak przy użyciu serię poleceń 240 00:19:01,390 --> 00:19:05,130 gdzie wykorzystać wyjście z jednego polecenia jako wejście do następnego polecenia. 241 00:19:05,130 --> 00:19:08,780 Można zrobić wiele rzeczy, wiele mądrych rzeczy. 242 00:19:08,780 --> 00:19:11,440 >> Questions? 243 00:19:12,910 --> 00:19:14,600 Okay. 244 00:19:14,600 --> 00:19:17,880 To jest to dla rur i przekierowania. 245 00:19:18,370 --> 00:19:24,090 >> Teraz możemy przejść do rzeczy, rzeczywistych rzeczy kodowania. 246 00:19:24,090 --> 00:19:29,100 Wewnątrz to PDF, zobaczysz tego polecenia, 247 00:19:29,100 --> 00:19:32,950 i będziesz chciał uruchomić tą komendę w swoim urządzeniu. 248 00:19:36,240 --> 00:19:42,250 wget jest polecenia dla dopiero się coś z internetu, w zasadzie, 249 00:19:42,250 --> 00:19:45,180 więc wget i to URL. 250 00:19:45,180 --> 00:19:49,110 Jeśli poszedł do tego adresu URL w przeglądarce, by go pobrać ten plik. 251 00:19:49,110 --> 00:19:52,510 I właśnie kliknął na niego, więc to pobrany plik dla mnie. 252 00:19:52,510 --> 00:19:55,650 Ale pisanie wget tej rzeczy wewnątrz terminalu 253 00:19:55,650 --> 00:19:58,620 jest po prostu się go ściągnąć do terminalu. 254 00:19:58,620 --> 00:20:02,750 Mam section5.zip, i będziemy chcieli, aby rozpakować section5.zip, 255 00:20:02,750 --> 00:20:06,520 która będzie Ci folder o nazwie section5, 256 00:20:06,520 --> 00:20:11,550 który będzie miał wszystkie pliki zamierzamy używać dziś w jej wnętrzu. 257 00:20:33,380 --> 00:20:37,710 Jak nazwy tych programów plików sugerują, że są nieco buggy, 258 00:20:37,710 --> 00:20:40,990 więc Twoim zadaniem jest dowiedzieć się, dlaczego przy użyciu gdb. 259 00:20:40,990 --> 00:20:44,560 Czy każdy musi je pobrać / wiedzieć, jak uzyskać ich pobraniu 260 00:20:44,560 --> 00:20:47,480 do swojego urządzenia? Okay. 261 00:20:47,480 --> 00:20:56,400 >> Bieganie ./buggy1, to powie Segmentation fault (core dumped) 262 00:20:56,400 --> 00:21:00,500 które w każdej chwili można uzyskać segfault, to jest złe. 263 00:21:00,500 --> 00:21:03,810 W jakich okolicznościach dostajesz segfault? 264 00:21:03,810 --> 00:21:08,210 [Uczeń] dereferencji wskaźnika pustego. >> Tak. Tak, że jeden z przykładów. 265 00:21:08,210 --> 00:21:11,580 Dereferencji pustego wskaźnika masz zamiar dostać segfault. 266 00:21:11,580 --> 00:21:16,720 Co segfault oznacza to jesteś dotykając pamięci nie należy dotykać. 267 00:21:16,720 --> 00:21:21,350 Więc dereferencji pustego wskaźnika dotyka adres 0, 268 00:21:21,350 --> 00:21:28,060 iw zasadzie wszystkie komputery w dzisiejszych czasach, że 0 adres pamięci nie należy dotykać. 269 00:21:28,060 --> 00:21:31,920 Więc dlatego dereferencji wskaźnika null wyniki w segfault. 270 00:21:31,920 --> 00:21:37,210 Gdy zdarzy Ci się nie zainicjować wskaźnik, to ma wartość śmieci, 271 00:21:37,210 --> 00:21:41,520 i tak przy próbie dereference to, najprawdopodobniej jesteś dotykając pamięć 272 00:21:41,520 --> 00:21:43,540 , że jest w środku pustkowia. 273 00:21:43,540 --> 00:21:45,650 Jeśli zdarzy ci się mieć szczęście i wartość śmieci 274 00:21:45,650 --> 00:21:48,440 się wskazywać na gdzieś na stosie czy coś, 275 00:21:48,440 --> 00:21:50,820 następnie po dereference że wskaźnik, które nie zostały zainicjowane, 276 00:21:50,820 --> 00:21:52,730 nic się nie udać. 277 00:21:52,730 --> 00:21:55,480 Ale jeśli jest skierowany do, powiedzmy, gdzieś między stosu i sterty, 278 00:21:55,480 --> 00:21:59,850 czy to wskazuje tylko gdzieś, że nie był używany przez program jeszcze, 279 00:21:59,850 --> 00:22:02,240 to jesteś dotykając pamięci nie należy dotykać i segfault. 280 00:22:02,240 --> 00:22:06,370 Kiedy piszesz funkcji rekurencyjnej i recurses zbyt wiele razy 281 00:22:06,370 --> 00:22:08,720 a stos rośnie zbyt duży i zderza stosu do rzeczy 282 00:22:08,720 --> 00:22:12,270 że nie powinno być kolizji z, jesteś dotykając pamięci nie należy dotykać, 283 00:22:12,270 --> 00:22:14,810 więc segfault. 284 00:22:14,810 --> 00:22:17,010 To, co segfault jest. 285 00:22:17,010 --> 00:22:21,810 >> To również z tego samego powodu, że jeśli ciąg jak - 286 00:22:21,810 --> 00:22:23,930 wróćmy do poprzedniego programu. 287 00:22:23,930 --> 00:22:28,530 W hello.c--jestem po prostu się do czegoś innego. 288 00:22:28,530 --> 00:22:33,770 char * s = "hello world!"; 289 00:22:33,770 --> 00:22:42,310 Jeśli używam * s = coś lub s [0] = 'X'; 290 00:22:42,310 --> 00:22:47,290 należy więc witam. / hello, dlaczego że segfault? 291 00:22:48,410 --> 00:22:51,250 Dlaczego to segfault? 292 00:22:55,660 --> 00:22:57,890 Czego można się spodziewać się stanie? 293 00:22:57,890 --> 00:23:06,640 Jeżeli zrobiłem printf ("% s \ n", s); co można się spodziewać do druku? 294 00:23:06,640 --> 00:23:09,930 [Uczeń] X hello. >> Tak. 295 00:23:09,930 --> 00:23:15,140 Problem jest, że kiedy zadeklarować ciąg jak to, 296 00:23:15,140 --> 00:23:18,190 s jest wskaźnik, który pójdzie na stos, 297 00:23:18,190 --> 00:23:25,880 i co s wskazuje na to łańcuch, który jest zawarty w pamięci tylko do odczytu. 298 00:23:25,880 --> 00:23:30,560 Więc po prostu nazwą, pamięci tylko do odczytu, należy się pomysł 299 00:23:30,560 --> 00:23:33,010 że jeśli chcesz zmienić to, co znajduje się w pamięci tylko do odczytu, 300 00:23:33,010 --> 00:23:36,670 robisz coś, czego nie powinien robić z pamięcią i segfault. 301 00:23:36,670 --> 00:23:45,360 To jest rzeczywiście wielka różnica między char * s, a char s []. 302 00:23:45,360 --> 00:23:48,790 Więc char s [], teraz ten ciąg ma być położony na stosie, 303 00:23:48,790 --> 00:23:53,960 i stos nie jest tylko do odczytu, co oznacza, że ​​powinno to działać całkiem dobrze. 304 00:23:55,500 --> 00:23:57,370 I to robi. 305 00:23:57,370 --> 00:24:06,250 Pamiętaj, że gdy zrobić char * s = "Hello World!", S sam w sobie jest na stosie 306 00:24:06,250 --> 00:24:10,390 ale s wskazuje gdzieś indziej, i że gdzieś dzieje się tylko do odczytu. 307 00:24:10,390 --> 00:24:15,640 Ale char s [] jest po prostu coś na stosie. 308 00:24:17,560 --> 00:24:21,760 Więc to jest kolejny przykład segfault dzieje. 309 00:24:21,760 --> 00:24:27,820 >> Widzieliśmy, że ./buggy1 spowodowało segfault. 310 00:24:27,820 --> 00:24:31,810 Teoretycznie nie powinno się patrzeć na buggy1.c natychmiast. 311 00:24:31,810 --> 00:24:35,170 Zamiast tego, będziemy patrzeć na to przez gdb. 312 00:24:35,170 --> 00:24:37,750 Zauważ, że gdy pojawi się Segmentation fault (core dumped) 313 00:24:37,750 --> 00:24:40,850 masz ten plik tutaj zwanego rdzenia. 314 00:24:40,850 --> 00:24:45,200 Jeśli ls-l, to widzimy, że rdzeń jest zazwyczaj dość duży plik. 315 00:24:45,200 --> 00:24:51,580 Jest to liczba bajtów pliku, więc wygląda na to, że to 250-coś kilobajtów. 316 00:24:51,580 --> 00:24:56,120 Powodem tego jest, że to, co faktycznie jest zrzutu 317 00:24:56,120 --> 00:25:01,410 jest, gdy twoje awarii programu, stan pamięci programu 318 00:25:01,410 --> 00:25:05,230 tylko zostanie skopiowana i wklejona do tego pliku. 319 00:25:05,230 --> 00:25:07,270 Zostaje skierowana do tego pliku. 320 00:25:07,270 --> 00:25:13,060 Program ten, gdy był uruchomiony, stało się mieć użycie pamięci około 250 kilobajtów, 321 00:25:13,060 --> 00:25:17,040 i tak, że to, co mnie wrzucano do tego pliku. 322 00:25:17,040 --> 00:25:23,630 Możesz teraz spojrzeć na plik jeśli robimy gdb buggy1 rdzeń. 323 00:25:23,630 --> 00:25:30,130 Możemy tylko zrobić gdb buggy1, i że będzie po prostu uruchomić gdb regularnie 324 00:25:30,130 --> 00:25:33,800 używając buggy1 jako pliku wejściowego. 325 00:25:33,800 --> 00:25:38,260 Ale jeśli nie gdb buggy1 rdzeń, to jest to konkretnie zamierza uruchomić gdb 326 00:25:38,260 --> 00:25:40,330 patrząc na ten plik jądra. 327 00:25:40,330 --> 00:25:45,560 I mówisz buggy1 dochodowe gdb wie, że plik pochodzi z rdzenia buggy1 programu. 328 00:25:45,560 --> 00:25:49,580 Więc gdb buggy1 rdzeń będzie natychmiast przynieść nam 329 00:25:49,580 --> 00:25:52,060 w którym program się zakończyć. 330 00:25:57,720 --> 00:26:02,340 Widzimy tutaj Program zakończony sygnałem 11, Segmentation fault. 331 00:26:02,340 --> 00:26:10,110 Zdarzy nam się zobaczyć linię montażu, które prawdopodobnie nie jest bardzo pomocne. 332 00:26:10,110 --> 00:26:15,360 Ale jeśli wpiszesz BT lub prześledzić, że będzie to funkcja 333 00:26:15,360 --> 00:26:19,430 to daje nam listę naszych aktualnych ramek stosu. 334 00:26:19,430 --> 00:26:23,150 Więc backtrace. Wygląda na to, że tylko dwa stosu ramek. 335 00:26:23,150 --> 00:26:26,310 Pierwszy to nasz główny ramki stosu, 336 00:26:26,310 --> 00:26:29,810 a drugi stack frame dla tej funkcji, które przebywają w, 337 00:26:29,810 --> 00:26:34,440 która wygląda jak mamy tylko kod montażowa. 338 00:26:34,440 --> 00:26:38,050 Więc wróćmy do naszej głównej funkcji, 339 00:26:38,050 --> 00:26:42,300 a do tego nie możemy zrobić ramkę 1 i myślę, że możemy również zrobić w dół, 340 00:26:42,300 --> 00:26:45,160 ale prawie nigdy nie zrobić dół - lub w górę. Tak. 341 00:26:45,160 --> 00:26:50,710 W górę iw dół. Up przynosi jedną ramkę stosu, aż cię sprowadza w dół ramki stosu. 342 00:26:50,710 --> 00:26:53,240 Staram się nie używać. 343 00:26:53,240 --> 00:26:59,120 Właśnie specjalnie powiedzieć rama 1, który jest pójść do klatki z etykietą 1. 344 00:26:59,120 --> 00:27:01,750 Rama 1 przyniesie nas do głównej ramki stosu, 345 00:27:01,750 --> 00:27:05,570 i mówi tu wiersz kodu my będziemy na. 346 00:27:05,570 --> 00:27:07,950 Jeśli chcieliśmy jeszcze kilka linijek kodu, możemy powiedzieć, listy, 347 00:27:07,950 --> 00:27:11,280 a to da nam wszystkie linie kodu wokół niego. 348 00:27:11,280 --> 00:27:13,360 Linia my segfaulted co było 6: 349 00:27:13,360 --> 00:27:17,360 if (strcmp ("CS50 rocks", argv [1]) == 0). 350 00:27:17,360 --> 00:27:24,130 Jeśli nie jest to oczywiste, ale można dostać prosto z tu tylko przez myślenie dlaczego segfaulted. 351 00:27:24,130 --> 00:27:28,800 Ale możemy go o jeden krok dalej i powiedzieć: "Dlaczego argv [1] segfault?" 352 00:27:28,800 --> 00:27:38,830 Print niech argv [1], i to wygląda jakby 0x0, co jest wskaźnikiem NULL. 353 00:27:38,830 --> 00:27:44,750 Jesteśmy strcmping CS50 skały i Null, i tak, że zamierza segfault. 354 00:27:44,750 --> 00:27:48,280 I dlaczego jest argv [1] null? 355 00:27:48,640 --> 00:27:51,280 [Uczeń] Ponieważ nie dać mu żadnych argumentów wiersza polecenia. 356 00:27:51,280 --> 00:27:53,390 Tak. Nie dać mu żadnych argumentów wiersza polecenia. 357 00:27:53,390 --> 00:27:58,460 Więc ./buggy1 tylko będzie mieć argv [0] będzie ./buggy1. 358 00:27:58,460 --> 00:28:02,100 To nie będzie mieć argv [1], tak, że zamierza segfault. 359 00:28:02,100 --> 00:28:07,450 Ale jeśli zamiast tego zrobić tylko CS50, to powie Dostajesz D 360 00:28:07,450 --> 00:28:09,950 ponieważ to, co to ma robić. 361 00:28:09,950 --> 00:28:15,240 Patrząc na buggy1.c, to ma się drukować "Dostajesz D" - 362 00:28:15,240 --> 00:28:20,820 Jeśli argv [1] nie jest "CS50 skały", "Dostajesz D", inaczej "Masz!" 363 00:28:20,820 --> 00:28:25,660 Więc jeśli chcemy, musimy to porównanie za prawdziwe, 364 00:28:25,660 --> 00:28:28,710 co oznacza, że ​​porównuje się do 0. 365 00:28:28,710 --> 00:28:31,100 Więc argv [1] musi być "CS50 skały". 366 00:28:31,100 --> 00:28:35,660 Jeśli chcesz to zrobić z wiersza poleceń, należy użyć \ uciec z miejsca. 367 00:28:35,660 --> 00:28:41,690 Więc CS50 \ skały i masz A! 368 00:28:41,690 --> 00:28:44,060 Jeśli tego nie zrobisz ukośnika, dlaczego to nie działa? 369 00:28:44,060 --> 00:28:47,190 [Uczeń] To dwa różne argumenty. >> Tak. 370 00:28:47,190 --> 00:28:52,540 Argv [1] będzie CS50, a argv [2] będzie skał. Okay. 371 00:28:52,540 --> 00:28:56,470 >> Teraz ./buggy2 będzie segfault ponownie. 372 00:28:56,470 --> 00:29:01,880 Zamiast otwierać je swoim pliku rdzenia, po prostu otworzyć buggy2 bezpośrednio, 373 00:29:01,880 --> 00:29:05,000 tak gdb buggy2. 374 00:29:05,000 --> 00:29:09,590 Teraz jeśli tylko uruchomić nasz program, to jest to powie Program otrzymał sygnał SIGSEGV, 375 00:29:09,590 --> 00:29:15,530 który jest segfault sygnał, i to, gdzie to się stało, aby się stało. 376 00:29:15,530 --> 00:29:21,250 Patrząc na backtrace, widzimy, że byliśmy w oh_no funkcyjnego, 377 00:29:21,250 --> 00:29:23,900 który został powołany przez Dinky funkcji, który został nazwany przez Binky funkcyjnego, 378 00:29:23,900 --> 00:29:26,460 który został powołany przez głównego. 379 00:29:26,460 --> 00:29:31,680 Widzimy również argumenty do tych funkcji. 380 00:29:31,680 --> 00:29:34,680 Argument Dinky i Binky był 1. 381 00:29:34,680 --> 00:29:44,390 Jeśli podajemy funkcję oh_no, widzimy, że jest po prostu robi oh_no char ** s = null; 382 00:29:44,390 --> 00:29:47,410 * S = "BOOM"; 383 00:29:47,410 --> 00:29:50,330 Dlaczego miałoby to się nie uda? 384 00:29:54,330 --> 00:29:58,380 [Uczeń] Nie można dereference zerowy wskaźnik? >> Tak. 385 00:29:58,380 --> 00:30:06,090 To jest po prostu mówiąc s jest równe NULL, niezależnie czy to dzieje się char **, 386 00:30:06,090 --> 00:30:12,070 które, w zależności od sposobu jego interpretacji, to może być wskaźnik do wskaźnika do łańcucha 387 00:30:12,070 --> 00:30:15,550 lub tablica łańcuchów. 388 00:30:15,550 --> 00:30:21,430 To s jest NULL, więc * s jest dereferencji wskaźnika pustego, 389 00:30:21,430 --> 00:30:24,800 i tak to będzie się zawieszał. 390 00:30:24,800 --> 00:30:27,540 Jest to jeden z najszybszych sposobów można ewentualnie segfault. 391 00:30:27,540 --> 00:30:31,300 To jest po prostu stwierdzenie wskaźnika pustego i natychmiast segfaulting. 392 00:30:31,300 --> 00:30:34,570 To właśnie oh_no robi. 393 00:30:34,570 --> 00:30:43,400 Jeśli idziemy jedną klatkę, a następnie jedziemy do dostać się do funkcji, która wywołała oh_no. 394 00:30:43,400 --> 00:30:44,830 Muszę zrobić to. 395 00:30:44,830 --> 00:30:48,610 Jeśli nie wprowadzić polecenie i po prostu naciśnij Enter ponownie, 396 00:30:48,610 --> 00:30:52,350 będzie po prostu powtórzyć poprzednie polecenie, że uciekł. 397 00:30:52,350 --> 00:30:56,610 Jesteśmy w 1 ramy. 398 00:30:56,610 --> 00:31:04,650 Wymienienie tej ramki, widzimy tutaj jest nasza funkcja. 399 00:31:04,650 --> 00:31:08,520 Można trafić listę ponownie, lub możesz zrobić listę 20 i będzie zawierać więcej. 400 00:31:08,520 --> 00:31:13,640 Przemiły funkcja mówi, że jeśli i jest 1, a następnie przejść do funkcji oh_no, 401 00:31:13,640 --> 00:31:15,960 jeszcze pójść do Slinky funkcji. 402 00:31:15,960 --> 00:31:18,700 I wiem, że jest 1, bo stało się tutaj, aby zobaczyć 403 00:31:18,700 --> 00:31:22,560 że przemiły została wywołana z argumentem 1. 404 00:31:22,560 --> 00:31:27,560 Można też po prostu są drukowane i będę to powiedzieć, że jest 1. 405 00:31:27,560 --> 00:31:33,770 Jesteśmy obecnie w Dinky, a jeśli idziemy inną ramkę, wiemy, będziemy w końcu w Binky. 406 00:31:33,770 --> 00:31:36,600 Up. Teraz jesteśmy w Binky. 407 00:31:36,600 --> 00:31:41,340 Wymieniając tę ​​funkcję - listy z przed pół przerwała mi - 408 00:31:41,340 --> 00:31:52,670 Zaczęło się tak, jakbym to 0, a następnie będziemy nazywać oh_no, inaczej nazwać przemiły. 409 00:31:52,670 --> 00:31:57,000 Wiemy, byłem 1, więc wezwał przemiły. 410 00:31:57,000 --> 00:32:05,030 A teraz wracamy do głównego, a głównym jest tylko będzie int i = rand ()% 3; 411 00:32:05,030 --> 00:32:08,790 To jest po prostu dać ci losowy numer, który jest albo 0, 1 lub 2. 412 00:32:08,790 --> 00:32:12,780 To się nazywają Binky z tym numerem, a powróci 0. 413 00:32:12,780 --> 00:32:16,700 Patrząc na to, 414 00:32:16,700 --> 00:32:19,880 spacerach z programu ręcznie bez uruchamiania go natychmiast 415 00:32:19,880 --> 00:32:25,400 należy ustawić punkt przerwy w głównych, co oznacza, że ​​podczas uruchamiania programu 416 00:32:25,400 --> 00:32:31,020 Twój program uruchamia się, dopóki nie natrafi na punkt przerwania. 417 00:32:31,020 --> 00:32:35,450 Tak więc uruchomienie programu, to będzie działać i wtedy uderzył w głównej funkcji i przestanie działać. 418 00:32:35,450 --> 00:32:44,700 Teraz jesteśmy w środku główny i krok lub następny przyniesie nas do następnego wiersza kodu. 419 00:32:44,700 --> 00:32:47,050 Możesz zrobić krok lub następnego. 420 00:32:47,050 --> 00:32:51,800 Uderzając obok, teraz został ustawiony na rand ()% 3, więc możemy drukować wartość zmiennej, 421 00:32:51,800 --> 00:32:55,280 i powie I jest 1. 422 00:32:55,280 --> 00:32:58,110 Teraz to ma znaczenie, czy używamy następnego lub krok. 423 00:32:58,110 --> 00:33:01,000 Myślę, że chodziło w poprzednim, ale chcemy wykorzystać następny. 424 00:33:01,000 --> 00:33:06,000 Jeśli używamy krok, wychodzimy do funkcji, co oznacza, spojrzeć na coś rzeczywistego 425 00:33:06,000 --> 00:33:07,940 że dzieje się wewnątrz Binky. 426 00:33:07,940 --> 00:33:10,510 Jeśli używamy obok, to znaczy iść na funkcję 427 00:33:10,510 --> 00:33:14,070 i po prostu przejść do następnego wiersza kodu w naszej głównej funkcji. 428 00:33:14,070 --> 00:33:17,900 Tutaj na tej linii, byłem w którym powiedział, rand ()% 3; 429 00:33:17,900 --> 00:33:21,320 jeśli zrobiłem krok, byłoby to do wdrażania rand 430 00:33:21,320 --> 00:33:25,110 i spojrzeć na to, co się tam dzieje, i mogłem przejść przez funkcję rand. 431 00:33:25,110 --> 00:33:26,920 Ale nie dbam o funkcji rand. 432 00:33:26,920 --> 00:33:30,190 Chcę tylko, aby przejść do następnego wiersza kodu w głównym, więc używam dalej. 433 00:33:30,190 --> 00:33:35,800 Ale teraz dbam o Binky funkcji, więc chcę wkraczać do tego. 434 00:33:35,800 --> 00:33:37,730 Teraz jestem w Binky. 435 00:33:37,730 --> 00:33:42,040 Pierwsza linia kodu powie if (i == 0), to krok, 436 00:33:42,040 --> 00:33:44,930 widzimy, skończymy na Dinky. 437 00:33:44,930 --> 00:33:51,620 Jeśli my, lista rzeczy, widzimy, że jest to sprawdzone i = 0. 438 00:33:51,620 --> 00:33:55,470 i nie jest równa 0, więc udaliśmy się do innego stanu, 439 00:33:55,470 --> 00:33:59,540 który będzie wywołać przemiły (i). 440 00:33:59,540 --> 00:34:04,030 Możesz się mylić. 441 00:34:04,030 --> 00:34:07,380 Jeśli patrzeć tylko na tych liniach bezpośrednio, można by pomyśleć, if (i == 0), 442 00:34:07,380 --> 00:34:10,800 ok, to ja się o krok, a teraz jestem w Dinky (i), 443 00:34:10,800 --> 00:34:14,120 można by pomyśleć, że musi oznaczać i = 0 lub coś. 444 00:34:14,120 --> 00:34:18,980 Nie, to po prostu oznacza, że ​​wie, może przykleić bezpośrednio do Dinky linii (i). 445 00:34:18,980 --> 00:34:23,300 Bo nie jest 0, następny krok nie skończy się na inny. 446 00:34:23,300 --> 00:34:26,239 Else nie linia to się zatrzyma jest. 447 00:34:26,239 --> 00:34:31,570 To po prostu się przejść do następnej linii może rzeczywiście wykonać, który jest przemiły (i). 448 00:34:31,570 --> 00:34:36,090 Wkraczającego Dinky (i), zobaczymy, czy (i == 1). 449 00:34:36,090 --> 00:34:42,670 Wiemy, i = 1, więc gdy wychodzimy, wiemy, mamy zamiar skończyć w oh_no 450 00:34:42,670 --> 00:34:46,489 bo = 1 nazywa oh_no funkcji, które można wejść do, 451 00:34:46,489 --> 00:34:52,969 który będzie ustawiony char ** s = NULL i natychmiast "boom". 452 00:34:54,270 --> 00:34:59,690 I wtedy rzeczywiście patrząc na realizację buggy2, 453 00:34:59,690 --> 00:35:04,590 to, i jest tylko coraz losowy numer - 0, 1, lub 2 - wywołanie Binky, 454 00:35:04,590 --> 00:35:10,610 co jeśli i jest 0 wywołuje oh_no, w przeciwnym wypadku zwraca przemiły, który pojawia się tutaj. 455 00:35:10,610 --> 00:35:18,100 Jeśli i jest 1, call oh_no, inaczej nazwać Slinky, który zbliża się tu, 456 00:35:18,100 --> 00:35:20,460 jeśli i jest 2, zadzwoń oh_no. 457 00:35:20,460 --> 00:35:24,720 Ja nawet nie myślę, że jest sposób - 458 00:35:24,720 --> 00:35:30,030 Czy ktoś widział sposób dokonywania to program, który nie będzie się wysypać? 459 00:35:30,030 --> 00:35:37,530 Bo chyba jestem brakuje czegoś, jeżeli i jest 0, będziesz natychmiast segfault, 460 00:35:37,530 --> 00:35:41,250 jeszcze udać się do funkcji, która jest 1 jeśli i wy segfault, 461 00:35:41,250 --> 00:35:44,540 jeszcze udać się do funkcji, gdzie jeśli i jest 2 Państwo segfault. 462 00:35:44,540 --> 00:35:46,810 Więc nie ma znaczenia, co robisz, segfault. 463 00:35:46,810 --> 00:35:52,380 >> Chyba jeden sposób mocowania byłoby zamiast robić char ** s = null, 464 00:35:52,380 --> 00:35:55,610 można przydzielić miejsca na ten ciąg znaków. 465 00:35:55,610 --> 00:36:04,230 Moglibyśmy zrobić malloc (sizeof) - sizeof co? 466 00:36:09,910 --> 00:36:15,190 [Uczeń] (char) * 5? >> Czy to wydaje się słuszne? 467 00:36:15,190 --> 00:36:21,060 Jestem zakładając, że to zadziała, jeśli faktycznie zabrakło, ale to nie to co szukam. 468 00:36:24,400 --> 00:36:32,940 Zobacz na typu S. Dodajmy int *, więc int * x. 469 00:36:32,940 --> 00:36:35,600 Chciałbym zrobić malloc (sizeof (int)). 470 00:36:35,600 --> 00:36:40,490 Albo gdybym chciał tablicy 5, chciałbym zrobić (sizeof (int) * 5); 471 00:36:40,490 --> 00:36:44,210 Co jeśli mam int **? 472 00:36:46,260 --> 00:36:49,140 Co bym malloc? 473 00:36:49,140 --> 00:36:53,510 [Uczeń] Wielkość wskaźnika. >> Tak. (Sizeof (int *)); 474 00:36:53,510 --> 00:36:56,960 To samo tutaj. 475 00:36:56,960 --> 00:37:01,280 Chcę (sizeof (char *)); 476 00:37:06,170 --> 00:37:12,840 To będzie przydzielić miejsce dla wskaźnika, który wskazuje na "boom". 477 00:37:12,840 --> 00:37:15,330 I nie trzeba przydzielić miejsce dla "boom" sam 478 00:37:15,330 --> 00:37:17,210 bo to jest w zasadzie odpowiednikiem tego, co powiedziałem wcześniej 479 00:37:17,210 --> 00:37:20,870 char * x = "BOOM". 480 00:37:20,870 --> 00:37:27,950 "Boom" już istnieje. Dzieje się tak, aby występować w obszarze tylko do odczytu z pamięci. 481 00:37:27,950 --> 00:37:35,200 Ale to już istnieje, co oznacza, że ​​ten wiersz kodu, jeśli s jest char **, 482 00:37:35,200 --> 00:37:43,900 następnie * s jest char * i jesteś ustawienie tego char * wskazać na "boom". 483 00:37:43,900 --> 00:37:50,040 Gdybym chciał skopiować "boom" w S, to musiałbym przeznaczyć przestrzeń dla tych. 484 00:37:55,170 --> 00:38:03,900 Zrobię * s = malloc (sizeof (char) * 5); 485 00:38:03,900 --> 00:38:06,210 Dlaczego 5? 486 00:38:06,210 --> 00:38:10,860 Dlaczego nie 4? To wygląda jak "boom" jest 4 znaków. >> [Uczeń] znak null. 487 00:38:10,860 --> 00:38:14,580 Tak. Wszystkie Twoje ciągi będą potrzebne znak null. 488 00:38:14,580 --> 00:38:23,590 Teraz można zrobić coś jak strcat - Co to jest funkcja kopiowania ciąg? 489 00:38:23,590 --> 00:38:28,520 [Uczeń] CPY? >> Strcpy. 490 00:38:28,520 --> 00:38:32,700 strcpy człowiek. 491 00:38:36,120 --> 00:38:39,590 Więc strcpy lub strncpy. 492 00:38:39,590 --> 00:38:43,410 strncpy jest nieco bezpieczniejsze, ponieważ można dokładnie określić, ile znaków, 493 00:38:43,410 --> 00:38:46,190 ale tutaj to nie ma znaczenia, bo wiemy. 494 00:38:46,190 --> 00:38:50,340 Więc strcpy i patrzeć w argumentach. 495 00:38:50,340 --> 00:38:53,100 Pierwszy argument jest nasz cel. 496 00:38:53,100 --> 00:38:56,770 Drugi argument jest nasze źródło. 497 00:38:56,770 --> 00:39:10,310 Mamy zamiar skopiować do naszego docelowego * s wskaźnik "BOOM". 498 00:39:10,310 --> 00:39:19,820 Dlaczego warto to zrobić z strcpy zamiast po prostu to, co mieliśmy przed 499 00:39:19,820 --> 00:39:22,800 z * s = "BOOM"? 500 00:39:22,800 --> 00:39:28,630 Jest powód, możesz to zrobić, ale co to jest powód? 501 00:39:28,630 --> 00:39:31,940 [Uczeń] Jeśli chcesz coś zmienić w "boom". >> Tak. 502 00:39:31,940 --> 00:39:37,950 Teraz mogę zrobić coś jak s [0] = 'X'; 503 00:39:37,950 --> 00:39:48,190 bo s wskazuje na stertę i że przestrzeń na stercie, że s jest skierowana do 504 00:39:48,190 --> 00:39:52,320 jest wskaźnikiem do więcej miejsca na stercie, który jest przechowywanie "boom". 505 00:39:52,320 --> 00:39:55,150 Więc to kopia "boom" jest przechowywana w stercie. 506 00:39:55,150 --> 00:39:58,780 Jest technicznie dwa egzemplarze "boom" w naszym programie. 507 00:39:58,780 --> 00:40:03,500 Jest pierwszym, który jest po prostu podane przez "Boom" stałej strun 508 00:40:03,500 --> 00:40:09,250 i drugi egzemplarz "boom", strcpy stworzył kopię "boom". 509 00:40:09,250 --> 00:40:13,100 Ale kopia "boom" jest przechowywana na stercie, a sterty jesteś wolny, aby zmienić. 510 00:40:13,100 --> 00:40:17,250 Kupa nie jest tylko do odczytu, więc to oznacza, że ​​s [0] 511 00:40:17,250 --> 00:40:20,500 będzie pozwalają zmienić wartość "boom". 512 00:40:20,500 --> 00:40:23,130 To będzie pozwalają zmienić te znaki. 513 00:40:23,130 --> 00:40:26,640 >> Questions? 514 00:40:27,740 --> 00:40:29,290 Okay. 515 00:40:29,290 --> 00:40:35,500 >> Przechodząc do buggy3, niech gdb buggy3. 516 00:40:35,500 --> 00:40:39,840 Po prostu uruchom go i widzimy mamy segfault. 517 00:40:39,840 --> 00:40:46,550 Jeśli backtrace, istnieją tylko dwie funkcje. 518 00:40:46,550 --> 00:40:52,970 Jeśli udamy się do naszej głównej funkcji, widzimy, że segfaulted na tej linii. 519 00:40:52,970 --> 00:41:00,180 Więc patrząc na tej linii, for (int wiersz = 0; fgets to rzeczy nie jest równa NULL; 520 00:41:00,180 --> 00:41:03,770 linia + +). 521 00:41:03,770 --> 00:41:08,010 Nasza poprzednia ramka nazwano _IO_fgets. 522 00:41:08,010 --> 00:41:10,720 Zobaczysz, że wiele z wbudowanych funkcji w języku C, 523 00:41:10,720 --> 00:41:15,350 że gdy pojawi się wysypać, nie będzie naprawdę zagadkowe nazwy funkcji 524 00:41:15,350 --> 00:41:18,090 podobnych _IO_fgets. 525 00:41:18,090 --> 00:41:21,770 Ale to będzie się odnosić do tego zaproszenia fgets. 526 00:41:21,770 --> 00:41:25,850 Gdzieś tutaj, jesteśmy segfaulting. 527 00:41:25,850 --> 00:41:30,340 Jeśli spojrzymy na argumenty do fgets, możemy wydrukować bufor. 528 00:41:30,340 --> 00:41:41,180 Miejmy wydrukować jako - Och, nie. 529 00:41:48,980 --> 00:41:51,900 Wydruku nie będzie działać dokładnie tak, jak chcemy. 530 00:41:55,460 --> 00:41:58,000 Spójrzmy na bieżącym programie. 531 00:42:02,200 --> 00:42:09,640 Bufor jest tablica znaków. Jest to tablica znaków z 128 znaków. 532 00:42:09,640 --> 00:42:14,980 Więc kiedy mówię, bufor wydruku, to będzie wydrukować te 128 znaków, 533 00:42:14,980 --> 00:42:18,300 co chyba jest to, co ma. 534 00:42:18,300 --> 00:42:21,390 Co szukałem to wydrukować adres bufora, 535 00:42:21,390 --> 00:42:23,680 ale to naprawdę nie ma mi powiedzieć wiele. 536 00:42:23,680 --> 00:42:30,770 Tak więc, gdy zdarza mi się powiedzieć tutaj bufor x, to pokazuje mi 0xbffff090, 537 00:42:30,770 --> 00:42:38,690 które, jeśli pamiętasz z wcześniejszych lub pewnym momencie Oxbffff bywa stos-owski region. 538 00:42:38,690 --> 00:42:46,020 Stos zmierza gdzieś zacząć tuż pod 0xc000. 539 00:42:46,020 --> 00:42:51,890 Po prostu widząc ten adres, wiem, że bufor dzieje się na stosie. 540 00:42:51,890 --> 00:43:04,500 Restartowanie mój program, uruchom, w górę, buforować widzieliśmy, był to ciąg znaków 541 00:43:04,500 --> 00:43:06,530 które są prawie bez znaczenia. 542 00:43:06,530 --> 00:43:12,270 Następnie wydrukować plik, co robi plik wyglądał? 543 00:43:15,120 --> 00:43:17,310 [Uczeń] Null. >> Tak. 544 00:43:17,310 --> 00:43:22,610 Plik jest z FILE * typu, więc jest to wskaźnik, 545 00:43:22,610 --> 00:43:26,610 a wartość tego wskaźnika jest null. 546 00:43:26,610 --> 00:43:33,240 Więc fgets będzie spróbować odczytać z tego wskaźnika w sposób pośredni, 547 00:43:33,240 --> 00:43:37,320 ale w celu uzyskania dostępu do tego wskaźnika, musi dereference go. 548 00:43:37,320 --> 00:43:40,550 Lub, w celu uzyskania dostępu do tego, co należy wskazując, to dereferences IT. 549 00:43:40,550 --> 00:43:43,810 Więc to dereferencji wskaźnika pustego i to naruszenia ochrony pamięci. 550 00:43:46,600 --> 00:43:48,730 Mógłbym wznowił go tam. 551 00:43:48,730 --> 00:43:52,170 Jeśli łamiemy na nasz główny punkt i uruchomić, 552 00:43:52,170 --> 00:43:57,320 Pierwsza linia kodu jest char * filename = "nonexistent.txt"; 553 00:43:57,320 --> 00:44:00,870 To powinno dać dość dużą wskazówkę, dlaczego ten program się nie powiedzie. 554 00:44:00,870 --> 00:44:06,080 Wpisując obok prowadzi mnie do następnej linii, gdzie otworzyć ten plik, 555 00:44:06,080 --> 00:44:11,140 , a następnie od razu dostać się do naszej linii, gdzie po I uderzył obok, to się wysypać. 556 00:44:11,140 --> 00:44:16,880 Czy ktoś chce wyrzucić powód dlaczego możemy być segfaulting? 557 00:44:16,880 --> 00:44:19,130 [Uczeń] Plik nie istnieje. >> Tak. 558 00:44:19,130 --> 00:44:22,250 To ma być podpowiedź 559 00:44:22,250 --> 00:44:29,570 że gdy otwieramy plik trzeba sprawdzić, że plik rzeczywiście istnieje. 560 00:44:29,570 --> 00:44:31,510 Więc, "nonexistent.txt"; 561 00:44:31,510 --> 00:44:34,700 Kiedy filename fopen do czytania, to wtedy trzeba powiedzieć, 562 00:44:34,700 --> 00:44:45,870 if (plik == NULL) i powiedzieć, printf ("Plik nie istnieje!" 563 00:44:45,870 --> 00:44:56,340 lub - jeszcze lepiej - filename); return 1; 564 00:44:56,340 --> 00:45:00,300 Więc teraz sprawdzić, czy to jest NULL 565 00:45:00,300 --> 00:45:03,930 zanim rzeczywiście trwają i próbuje odczytać z tego pliku. 566 00:45:03,930 --> 00:45:08,800 Możemy przerobić go po prostu zobaczyć, że to działa. 567 00:45:11,020 --> 00:45:14,970 I ma obejmować nowy wiersz. 568 00:45:21,090 --> 00:45:25,290 Więc teraz nonexistent.txt nie istnieje. 569 00:45:26,890 --> 00:45:30,040 Zawsze należy sprawdzić tego typu rzeczy. 570 00:45:30,040 --> 00:45:33,870 Należy zawsze sprawdzić, czy fopen zwraca wartość NULL. 571 00:45:33,870 --> 00:45:38,170 Zawsze należy sprawdzić, aby upewnić się, że malloc nie zwraca NULL, 572 00:45:38,170 --> 00:45:41,410 albo masz segfault. 573 00:45:42,200 --> 00:45:45,930 >> Teraz buggy4.c. 574 00:45:49,190 --> 00:45:58,440 Uruchomiony. Zgaduję, to czeka na wejście lub zapętlenie ewentualnie nieskończonym. 575 00:45:58,440 --> 00:46:01,870 Tak, to jest nieskończone zapętlenie. 576 00:46:01,870 --> 00:46:05,560 Więc buggy4. Wygląda na to, że jesteśmy nieskończone zapętlenie. 577 00:46:05,560 --> 00:46:12,590 Możemy przełamać w main, uruchomić nasz program. 578 00:46:12,590 --> 00:46:20,180 W gdb, dopóki skrót używasz jest jednoznaczna 579 00:46:20,180 --> 00:46:23,420 lub specjalne skróty, które świadczą dla Ciebie, 580 00:46:23,420 --> 00:46:29,020 następnie można użyć n użyć następny zamiast wpisywać się obok przez całą drogę. 581 00:46:29,020 --> 00:46:33,730 I teraz, kiedy został trafiony n raz, można po prostu naciśnij Enter, aby nie poddawać się następny 582 00:46:33,730 --> 00:46:36,640 zamiast trafić n Enter, n Wpisz, n Enter. 583 00:46:36,640 --> 00:46:44,630 Wygląda na to, że jestem w jakiejś pętli for, która jest ustawiona tablica [i] do 0. 584 00:46:44,630 --> 00:46:50,510 Wygląda na to, nigdy nie jestem wyrwanie się z tego dla pętli. 585 00:46:50,510 --> 00:46:54,780 Jeśli mogę wydrukować i, więc jest o 2, potem pójdę dalej. 586 00:46:54,780 --> 00:46:59,250 Będę print i, i jest 3, potem pójdę dalej. 587 00:46:59,250 --> 00:47:05,360 Będę drukować I i I jest 3. Następnie wydrukować i, i jest 4. 588 00:47:05,360 --> 00:47:14,520 Właściwie print sizeof (tablica), więc rozmiar tablicy jest 20. 589 00:47:16,310 --> 00:47:32,870 Ale wygląda na to jest jakaś specjalna komenda gdb aby jechać aż coś się wydarzy. 590 00:47:32,870 --> 00:47:37,620 To jak ustawienie warunku na wartość zmiennej. Ale nie pamiętam, co to jest. 591 00:47:37,620 --> 00:47:44,100 Jeśli więc nie poddawać się - 592 00:47:44,100 --> 00:47:47,120 Co pan mówi? Czego się wychować? 593 00:47:47,120 --> 00:47:50,500 [Uczeń] Nie wyświetla dodam - >> Tak. Więc wyświetlić mogę pomóc. 594 00:47:50,500 --> 00:47:54,530 Jeśli po prostu wyświetlić i, będzie można umieścić tutaj co wartość i jest 595 00:47:54,530 --> 00:47:56,470 więc nie trzeba go wydrukować za każdym razem. 596 00:47:56,470 --> 00:48:02,930 Jeśli tylko poddawać się Następnie patrz 0, 1, 2, 3, 4, 5, 0, 1, 2, 3, 4, 5, 0, 1, 2, 3, 4, 5. 597 00:48:02,930 --> 00:48:08,530 Coś się bardzo źle, a ja jest resetowane do 0. 598 00:48:13,330 --> 00:48:22,220 Patrząc na buggy4.c widzimy wszystko co się dzieje to int tablica [5]; 599 00:48:22,220 --> 00:48:26,200 for (i = 0; i <= sizeof (tablica); i + +) 600 00:48:26,200 --> 00:48:28,550 tablica [i] = 0; 601 00:48:28,550 --> 00:48:31,390 Co widzimy, że to źle? 602 00:48:31,390 --> 00:48:39,480 Jako podpowiedź, gdy robiła gdb buggy4 - Złammy main, run - 603 00:48:39,480 --> 00:48:45,980 Zrobiłem print sizeof (tablica), by zobaczyć, co jest warunkiem, gdzie powinien wreszcie wyrwać. 604 00:48:47,690 --> 00:48:51,100 Gdzie ja jestem? Czy mogę uruchomić? 605 00:48:51,100 --> 00:48:54,280 I nie zadeklarował jeszcze. 606 00:48:54,280 --> 00:48:58,680 Więc drukować sizeof (array) i to jest 20, 607 00:48:58,680 --> 00:49:06,690 który ma ponieważ moja tablica ma rozmiar 5 i to z 5 liczb całkowitych, 608 00:49:06,690 --> 00:49:12,410 więc cała sprawa powinna być 5 * sizeof (int) bajtów, gdzie sizeof (int) jest raczej 4. 609 00:49:12,410 --> 00:49:14,780 Więc sizeof (array) jest 20. 610 00:49:14,780 --> 00:49:17,420 Jakie powinny być? 611 00:49:17,420 --> 00:49:21,720 [Uczeń] podzielone przez sizeof (int). >> Tak, / sizeof (int). 612 00:49:21,720 --> 00:49:30,630 Wygląda na to, że nadal jest problem. Myślę, że to powinno być po prostu < 613 00:49:30,630 --> 00:49:36,960 ponieważ jest to prawie zawsze 00:49:44,860 Teraz pomyślmy o tym, dlaczego to było rzeczywiście zepsute. 615 00:49:44,860 --> 00:49:53,370 Czy ktoś domyśla się dlaczego i zresetować do 0 poprzez każdej iteracji pętli? 616 00:50:01,300 --> 00:50:09,350 Jedyne wewnątrz tutaj się dzieje jest to, że tablica [i] jest ustawiony na 0. 617 00:50:09,350 --> 00:50:15,350 Tak jakoś, ta linia kodu jest przyczyną naszego int i być ustawiony na 0. 618 00:50:16,730 --> 00:50:23,130 [Student] Czy to możliwe, ponieważ jest nadpisanie pamięci tej części I 619 00:50:23,130 --> 00:50:27,970 kiedy myśli, że to kolejny element z tablicy? >> [Bowden] Tak. 620 00:50:27,970 --> 00:50:33,880 Kiedy jesteśmy poza koniec naszej tablicy, 621 00:50:33,880 --> 00:50:39,870 jakoś, że przestrzeń, że jesteśmy nadrzędnego jest nadrzędne wartości i. 622 00:50:39,870 --> 00:50:48,030 I tak, jeśli spojrzymy na buggy4, złamać główny, bieg, 623 00:50:48,030 --> 00:50:53,120 niech wydrukować adres i. 624 00:50:53,120 --> 00:50:57,280 Wygląda na to, że to bffff124. 625 00:50:57,280 --> 00:51:03,930 Teraz drukowanie adresu tablicy [0]. 110. 626 00:51:03,930 --> 00:51:06,290 Co o [1]? 114. 627 00:51:06,290 --> 00:51:07,920 [2], 118. 628 00:51:07,920 --> 00:51:14,530 11c, 120. tablica [5] jest bfff124. 629 00:51:14,530 --> 00:51:26,990 Więc tablica [5] ma taki sam adres jak ja, co oznacza, że ​​tablica [5] i. 630 00:51:26,990 --> 00:51:30,720 Jeśli mają taki sam adres, są one tak samo. 631 00:51:30,720 --> 00:51:38,410 Więc kiedy możemy ustawić tablicę [5] do 0, więc ustawienie I do 0. 632 00:51:38,410 --> 00:51:46,070 A jeśli myślisz o tym w warunkach stosu, 633 00:51:46,070 --> 00:51:55,590 int i jest zadeklarowany pierwszy, co oznacza, że ​​ma trochę miejsca na stosie. 634 00:51:55,590 --> 00:52:04,730 Następnie tablica [5] jest rozdzielona, ​​tak to 20 bajty są alokowane na stosie. 635 00:52:04,730 --> 00:52:08,400 Więc zostanie przyznane pierwsze, to te 20 bajtów uzyskać przydzielone. 636 00:52:08,400 --> 00:52:11,400 Więc dzieje się tuż przed tablicy, 637 00:52:11,400 --> 00:52:19,230 i ze względu na sposób, jak powiedziałem w zeszłym tygodniu, gdy jest to technicznie stos rośnie w dół, 638 00:52:19,230 --> 00:52:28,520 kiedy indeks do tablicy, mamy zagwarantowane, że 0-sza pozycji w tablicy 639 00:52:28,520 --> 00:52:31,970 zawsze dzieje się przed pierwszą pozycję w tablicy. 640 00:52:31,970 --> 00:52:35,900 Jest to rodzaj jak narysowałem to w zeszłym tygodniu. 641 00:52:35,900 --> 00:52:42,210 Zauważ, że na dole mamy adres 0 i na górze mamy Max adresów. 642 00:52:42,210 --> 00:52:44,880 Stos jest zawsze rośnie w dół. 643 00:52:48,100 --> 00:52:53,500 Załóżmy, że mamy przeznaczyć i. 644 00:52:53,500 --> 00:52:59,680 Przydzielamy całkowitą i, co oznacza po prostu powiedzieć, tu całkowita i dostaje przydzielone. 645 00:52:59,680 --> 00:53:06,420 Następnie przydziela naszej tablicy 5 całkowite, co oznacza, że, pod 646 00:53:06,420 --> 00:53:11,230 ponieważ stos rośnie w dół, te 5 całkowitymi się przydzielone. 647 00:53:11,230 --> 00:53:15,900 Ale ze względu na to, jak działają zespoły, mamy gwarancję, że pierwsza pozycja w tablicy 648 00:53:15,900 --> 00:53:22,260 Adres zawsze mniejsza niż drugiej rzeczy w tablicy. 649 00:53:22,260 --> 00:53:28,270 Więc 0 pozycji tablicy zawsze ma się wydarzyć najpierw w pamięci, 650 00:53:28,270 --> 00:53:30,700 natomiast pozycja tablica 1 musi się zdarzyć, że po 651 00:53:30,700 --> 00:53:33,310 i położenie tablicy 2 ma nastąpić po tym, 652 00:53:33,310 --> 00:53:37,900 co oznacza, że ​​pozycja 0 tablica by się stało, gdzieś tutaj, 653 00:53:37,900 --> 00:53:40,690 Pozycja tablicy 1 powyżej, że stałoby się 654 00:53:40,690 --> 00:53:45,530 ponieważ przesuwa się w górę oznacza wyższe adresy ponieważ maksymalna adres jest tutaj. 655 00:53:45,530 --> 00:53:50,490 Więc tablica [0] tu, tablica [1] tu, tablica [2] tu, tablica [3] tutaj. 656 00:53:50,490 --> 00:53:55,620 Zauważ, jak zanim przydzielono liczbę całkowitą i całą drogę aż tutaj, 657 00:53:55,620 --> 00:54:01,040 jak iść dalej i dalej w naszej tablicy, jesteśmy coraz bliżej do naszej całkowitej i. 658 00:54:01,040 --> 00:54:07,640 Tak się składa, że ​​tablica [5], który jest o jedną pozycję poza naszą tablicę, 659 00:54:07,640 --> 00:54:13,010 jest dokładnie tam, gdzie całkowita Zdarzyło mi się być przydzielone. 660 00:54:13,010 --> 00:54:16,920 Więc to jest punkt, w którym my będziemy uderzając miejsca na stosie 661 00:54:16,920 --> 00:54:21,680 , która została przeznaczona na całkowitą i, i ruszamy, że do 0. 662 00:54:21,680 --> 00:54:26,160 >> To, w jaki sposób działa. Questions? Tak. 663 00:54:26,160 --> 00:54:30,710 [Uczeń] Nieważne. Okay. 664 00:54:30,710 --> 00:54:33,090 [Uczeń] Jak uniknąć tych rodzaju błędów? 665 00:54:33,090 --> 00:54:41,190 Są swego rodzaju błędów? Nie stosować C jako języka programowania. 666 00:54:41,190 --> 00:54:45,840 Używać języka, który ma granice tablicy kontroli. 667 00:54:45,840 --> 00:54:55,900 Tak długo, jak jesteś ostrożny, wystarczy, aby uniknąć mijając granice swojej tablicy. 668 00:54:55,900 --> 00:54:58,300 [Uczeń] Więc kiedy poszliśmy przeszłości granice swojej tablicy - 669 00:54:58,300 --> 00:55:01,840 [Bowden] To miejsce, gdzie wszystko zaczyna nie tak. >> [Uczeń] Oh, w porządku. 670 00:55:01,840 --> 00:55:05,730 Jak długo pozostać w pamięci przydzielonej dla Twojej tablicy, jesteś w porządku. 671 00:55:05,730 --> 00:55:12,400 Ale C nie wykonuje sprawdzanie błędów. Jeśli zrobić tablicę [1000], to chętnie tylko zmodyfikować, co się dzieje - 672 00:55:12,400 --> 00:55:16,500 Przechodzi do początku tablicy, a następnie idzie od pozycji 1000 i ustawia się na 0. 673 00:55:16,500 --> 00:55:20,000 To nie robi żadnej kontroli, tak och, to rzeczywiście nie ma 1000 rzeczy w nim. 674 00:55:20,000 --> 00:55:22,750 1000 jest poza co mam się zmieniać, 675 00:55:22,750 --> 00:55:26,940 mając na uwadze, Java czy coś dostaniesz tablicę z indeksu bounds 676 00:55:26,940 --> 00:55:29,820 lub indeks z wyjątkiem bounds. 677 00:55:29,820 --> 00:55:33,950 Dlatego wiele języków wyższych poziomów te rzeczy 678 00:55:33,950 --> 00:55:37,340 gdzie jeśli wykracza poza granice tablicy, nie uda 679 00:55:37,340 --> 00:55:40,070 tak, że nie można zmienić rzeczy spod Ciebie 680 00:55:40,070 --> 00:55:42,590 a potem wszystko pójdzie znacznie gorzej niż tylko coraz wyjątek 681 00:55:42,590 --> 00:55:44,940 mówiąc, że wyszedł poza koniec tablicy. 682 00:55:44,940 --> 00:55:50,970 [Uczeń] I tak powinno właśnie zmienił <= po prostu > [Bowden] Tak. 683 00:55:50,970 --> 00:55:54,800 Powinien on być 00:55:59,560 od sizeof (array) jest 20, ale chcemy tylko 5. >> [Uczeń] Racja. 685 00:55:59,560 --> 00:56:04,060 Więcej pytań? Okay. 686 00:56:04,060 --> 00:56:07,380 >> [Uczeń] Mam pytanie. >> Tak. 687 00:56:07,380 --> 00:56:16,440 [Uczeń] Co to jest rzeczywista zmiennej tablicy? 688 00:56:16,440 --> 00:56:20,000 [Bowden] Jak to, co jest tablica? 689 00:56:20,000 --> 00:56:24,930 Tablica sama w sobie jest symbolem. 690 00:56:24,930 --> 00:56:31,490 To jest po prostu adres rozpoczęcia 20 bajtów, które odwołują. 691 00:56:31,490 --> 00:56:38,070 Można traktować ją jako wskaźnik, ale jest stałym wskaźnikiem. 692 00:56:38,070 --> 00:56:44,140 Jak tylko robi się skompilowany, zmienna tablica już nie istnieje. 693 00:56:44,140 --> 00:56:48,210 [Uczeń] Więc jak to znaleźć rozmiar tablicy? 694 00:56:48,210 --> 00:56:54,130 Wielkość odnosi się do tablicy wielkości tego bloku, że symbol oznacza. 695 00:56:54,130 --> 00:57:01,240 Kiedy zrobić coś jak printf ("% p \ n", tablica); 696 00:57:01,240 --> 00:57:05,140 niech go uruchomić. 697 00:57:12,960 --> 00:57:15,530 Co ja zrobiłem źle? 698 00:57:15,530 --> 00:57:19,220 Array 'array' zgłaszać tutaj. 699 00:57:20,820 --> 00:57:23,200 O, tutaj. 700 00:57:23,200 --> 00:57:31,250 Clang jest mądry, a zdarza się, aby zauważyć, że oświadczyłem tablicę jako 5 elementów 701 00:57:31,250 --> 00:57:34,540 ale jestem do pozycji 1000 indeksowania. 702 00:57:34,540 --> 00:57:38,450 Może to zrobić, ponieważ są to tylko stałe. 703 00:57:38,450 --> 00:57:43,370 Można tylko iść tak daleko w zauważając, że będę poza granice tablicy. 704 00:57:43,370 --> 00:57:46,880 Zauważmy jednak, wcześniej, kiedy mieliśmy i są błędne, 705 00:57:46,880 --> 00:57:51,040 Nie można ewentualnie określić ile wartości mogłem podjąć, 706 00:57:51,040 --> 00:57:55,540 tak, że nie można ustalić, że był poza koniec tablicy. 707 00:57:55,540 --> 00:57:59,430 To tylko Clang będąc zdolny. 708 00:57:59,430 --> 00:58:03,340 >> Ale teraz zrobić buggy4. Co jeszcze robię źle? 709 00:58:03,340 --> 00:58:05,970 Pośrednio deklarowania funkcji biblioteki "printf". 710 00:58:05,970 --> 00:58:14,960 Będę chciał # include. 711 00:58:14,960 --> 00:58:18,710 Okay. Teraz pracuje buggy4. 712 00:58:18,710 --> 00:58:24,840 Drukowanie wartości tablicy jak ja tutaj, drukowania go jako wskaźnik 713 00:58:24,840 --> 00:58:30,060 coś drukuje, który wygląda tak - bfb8805c - co jakiś adres 714 00:58:30,060 --> 00:58:33,450 To w tym regionie stack-owski. 715 00:58:33,450 --> 00:58:41,820 Array sama jest jak wskaźnik, ale to nie jest rzeczywisty wskaźnik, 716 00:58:41,820 --> 00:58:45,410 od zwykłego wskaźnika możemy zmienić. 717 00:58:45,410 --> 00:58:54,700 Tablica to tylko niektóre stały. Do 20 bloków pamięci zaczynają się 0xbfb8805c adresowej. 718 00:58:54,700 --> 00:59:09,020 Więc bfb8805c poprzez ten adres +20- lub Chyba -20 - 719 00:59:09,020 --> 00:59:17,400 to wszystko z pamięci przeznaczonej na tej tablicy. 720 00:59:17,400 --> 00:59:20,350 Tablica, zmienna nie jest przechowywane w dowolnym miejscu. 721 00:59:20,350 --> 00:59:27,660 Kiedy jesteś kompilacji, kompilator - wave ręka na to - 722 00:59:27,660 --> 00:59:33,060 ale kompilator po prostu użyć, gdy wie, tablica jest. 723 00:59:33,060 --> 00:59:36,090 To, że nie wie, gdzie tablica zostanie uruchomiony, 724 00:59:36,090 --> 00:59:40,910 i tak zawsze może po prostu robić rzeczy w zakresie offsetu od tego początku. 725 00:59:40,910 --> 00:59:43,960 Nie potrzebujemy zmiennej samodzielnie reprezentować tablicę. 726 00:59:43,960 --> 00:59:53,730 Ale kiedy coś jak int * = p tablicy, teraz p jest wskaźnikiem, który wskazuje na tej tablicy 727 00:59:53,730 --> 00:59:57,830 a teraz p faktycznie istnieje na stosie. 728 00:59:57,830 --> 01:00:01,950 Jestem wolny, aby zmienić p. Mogę zrobić, p = malloc. 729 01:00:01,950 --> 01:00:06,500 Więc początkowo wskazał na tablicy, a teraz wskazuje do pewnego miejsca na stercie. 730 01:00:06,500 --> 01:00:09,620 Nie mogę Array = malloc. 731 01:00:09,620 --> 01:00:13,710 Jeśli Clang jest mądry, to krzycz na mnie tuż nietoperza. 732 01:00:17,000 --> 01:00:21,430 Faktycznie, jestem pewien, że gcc zrobi to zbyt. 733 01:00:21,430 --> 01:00:25,010 Więc typ array 'int [5] "nie jest przypisane. 734 01:00:25,010 --> 01:00:28,040 Nie można przypisać coś do typu tablicy 735 01:00:28,040 --> 01:00:30,500 ponieważ tablica jest po prostu stałą. 736 01:00:30,500 --> 01:00:34,760 Jest to symbol, który referencje te 20 bajtów. I nie można go zmienić. 737 01:00:34,760 --> 01:00:37,690 >> [Uczeń] A gdzie jest rozmiar tablicy przechowywane? 738 01:00:37,690 --> 01:00:40,670 [Bowden] To nie jest nigdzie zapisane. To kiedy jest kompilacją. 739 01:00:40,670 --> 01:00:46,310 Więc gdzie jest rozmiar tablicy przechowywane? 740 01:00:46,310 --> 01:00:51,870 Można używać tylko sizeof (array) wewnątrz funkcji, która tablica jest zadeklarował. 741 01:00:51,870 --> 01:01:03,150 Więc jeśli mogę zrobić kilka funkcji, Foo, i ja (int tablica []) 742 01:01:03,150 --> 01:01:10,450 printf ("% d \ n", sizeof (array)); 743 01:01:10,450 --> 01:01:21,330 a następnie w dół tu wywołać foo (tablica); 744 01:01:21,330 --> 01:01:24,840 wewnątrz tej funkcji - niech go uruchomić. 745 01:01:34,200 --> 01:01:36,840 To jest mądry Clang ponownie. 746 01:01:36,840 --> 01:01:43,890 To mówi mi, że parametr funkcji sizeof na tablicy 747 01:01:43,890 --> 01:01:46,690 zwróci rozmiar 'int *'. 748 01:01:46,690 --> 01:01:55,150 To byłby błąd, jeśli to nie jest to, co chciałem się stać. 749 01:01:55,150 --> 01:01:58,960 Miejmy faktycznie wyłączyć Werror. 750 01:02:14,950 --> 01:02:17,590 Ostrzeżenie. Ostrzeżenia są w porządku. 751 01:02:17,590 --> 01:02:19,960 Będzie nadal kompilacji ile ma ostrzeżenia. 752 01:02:19,960 --> 01:02:22,910 . / A.out będzie drukować 4. 753 01:02:22,910 --> 01:02:28,650 Ostrzeżenie, że został wygenerowany, wyraźnie wskazuje, co poszło źle. 754 01:02:28,650 --> 01:02:34,120 Ten int tablica jest po prostu będzie drukować sizeof (int *). 755 01:02:34,120 --> 01:02:39,790 Nawet jeśli mogę umieścić tablicę [5] tu, to jeszcze po prostu się do wydrukowania sizeof (int *). 756 01:02:39,790 --> 01:02:47,440 Więc jak najszybciej przekazać go do funkcji, rozróżnienie między tablicami i wskaźnikami 757 01:02:47,440 --> 01:02:49,670 nie istnieje. 758 01:02:49,670 --> 01:02:52,640 To dzieje się tablica, która została zadeklarowana na stos, 759 01:02:52,640 --> 01:02:58,300 ale jak tylko przekazać te wartości, które 0xbf bla, bla, bla do tej funkcji, 760 01:02:58,300 --> 01:03:03,350 wówczas wskaźnik wskazuje na tej tablicy na stosie. 761 01:03:03,350 --> 01:03:08,310 To znaczy, że sizeof zastosowanie tylko do funkcji, która została zadeklarowana tablica, 762 01:03:08,310 --> 01:03:11,230 co oznacza, że ​​podczas kompilacji z tej funkcji, 763 01:03:11,230 --> 01:03:17,330 kiedy Clang przechodzi tej funkcji, widzi tablicy jest int tablica wielkości 5. 764 01:03:17,330 --> 01:03:20,640 Więc widzi sizeof (tablica). Dobrze, że to 20. 765 01:03:20,640 --> 01:03:26,440 To właściwie jak sizeof zasadniczo działa w prawie wszystkich przypadkach. 766 01:03:26,440 --> 01:03:31,150 Sizeof nie jest funkcją, to jest operator. 767 01:03:31,150 --> 01:03:33,570 Nie nazywamy sizeof funkcję. 768 01:03:33,570 --> 01:03:38,280 Sizeof (int), kompilator będzie tylko tłumaczenie, że do 4. 769 01:03:41,480 --> 01:03:43,700 Masz? Okay. 770 01:03:43,700 --> 01:03:47,520 >> [Uczeń] Więc jaka jest różnica między sizeof (array) w głównym, w foo? 771 01:03:47,520 --> 01:03:52,840 To dlatego mówimy sizeof (tablica), co ma * typu int, 772 01:03:52,840 --> 01:03:57,120 natomiast macierz tu nie jest z typu int *, to int tablica. 773 01:03:57,120 --> 01:04:04,540 >> [Uczeń] Więc jeśli miał parametr w tablicy [] zamiast int tablicy *, 774 01:04:04,540 --> 01:04:09,230 by to oznaczało, że można jeszcze zmienić tablicę, bo teraz to jest wskaźnik? 775 01:04:09,230 --> 01:04:14,250 [Bowden] Podoba Ci się? >> [Uczeń] Tak. Można zmienić tablicę w funkcji teraz? 776 01:04:14,250 --> 01:04:18,420 [Bowden] Można zmienić tablicę w obu przypadkach. 777 01:04:18,420 --> 01:04:23,130 W obu tych przypadkach, jesteś wolny, aby powiedzieć, tablica [4] = 0. 778 01:04:23,130 --> 01:04:26,590 [Uczeń] Ale można zrobić punkt tablicy na coś innego? 779 01:04:26,590 --> 01:04:30,230 [Bowden] Oh. Tak. W każdym przypadku - >> [uczeń] Tak. 780 01:04:30,230 --> 01:04:38,410 [Bowden] rozróżnienie tablicy [] i int array *, nie ma. 781 01:04:38,410 --> 01:04:42,570 Możesz również zdobyć tablicę wielowymiarową tutaj 782 01:04:42,570 --> 01:04:47,050 dla niektórych wygodnej składni, ale to wciąż tylko wskaźnik. 783 01:04:47,050 --> 01:04:56,400 Oznacza to, że jestem wolny, aby zrobić tablicę = malloc (sizeof (int)), a teraz wskaż gdzie indziej. 784 01:04:56,400 --> 01:04:59,610 Ale tak jak jak to działa zawsze i na zawsze, 785 01:04:59,610 --> 01:05:03,210 Zmiana tej tablicy robiąc to wskazywać na coś innego 786 01:05:03,210 --> 01:05:07,570 nie zmienia tej tablicy w dół, bo to kopia argumentu 787 01:05:07,570 --> 01:05:10,780 nie wskaźnik do tego argumentu jest. 788 01:05:10,780 --> 01:05:16,070 I rzeczywiście, tak jak więcej wskazaniem, że jest to dokładnie to samo - 789 01:05:16,070 --> 01:05:21,100 już widziałem co wydruki tablicy drukowania - 790 01:05:21,100 --> 01:05:31,410 co, jeśli drukujemy adres tablicy lub adresu na adres tablicy 791 01:05:31,410 --> 01:05:36,290 do jednej z tych? 792 01:05:41,770 --> 01:05:45,220 Zignorujmy ten. 793 01:05:48,140 --> 01:05:51,660 Okay. To jest w porządku. Jest to teraz działa. / A.out. 794 01:05:51,660 --> 01:06:00,220 Array druku, drukowanie adres tablicy, to samo. 795 01:06:00,220 --> 01:06:02,870 Array po prostu nie istnieje. 796 01:06:02,870 --> 01:06:08,190 Ona wie, podczas drukowania tablicy, drukuje się symbol, który odnosi się do tych 20 bajtów. 797 01:06:08,190 --> 01:06:11,940 Drukowanie adres tablicy, dobrze, tablica nie istnieje. 798 01:06:11,940 --> 01:06:17,200 To nie ma adresu, więc to po prostu drukuje adres tych 20 bajtów. 799 01:06:20,820 --> 01:06:28,150 Tak szybko, jak skompilować w dół, podobnie jak w skompilowanego buggy4. / A.out, 800 01:06:28,150 --> 01:06:30,340 tablica nie istnieje. 801 01:06:30,340 --> 01:06:33,640 Wskaźniki istnieje. Tablice nie. 802 01:06:34,300 --> 01:06:38,060 Bloki pamięci reprezentujący tablicę nadal istnieją, 803 01:06:38,060 --> 01:06:43,270 ale zmienna tablicowa i zmienne tego typu nie istnieją. 804 01:06:46,260 --> 01:06:50,270 Są jak głównych różnic między tablicami i wskaźnikami 805 01:06:50,270 --> 01:06:55,590 są jak najszybciej dokonać wywołania funkcji, nie ma różnicy. 806 01:06:55,590 --> 01:07:00,460 Ale wewnątrz funkcji, która jest zadeklarowana sama tablica, sizeof działa inaczej 807 01:07:00,460 --> 01:07:05,190 drukuje się od wielkości bloków zamiast wielkości typu 808 01:07:05,190 --> 01:07:08,950 i nie można go zmienić, ponieważ jest to symbol. 809 01:07:08,950 --> 01:07:14,370 Drukowanie rzeczy i adres rzeczy wypisuje to samo. 810 01:07:14,370 --> 01:07:18,480 I to jest dość dużo. 811 01:07:18,480 --> 01:07:20,820 [Uczeń] Można powiedzieć, że jeszcze raz? 812 01:07:21,170 --> 01:07:24,170 I może coś przeoczyć. 813 01:07:24,170 --> 01:07:29,260 Array Drukowanie i adres tablicy wypisuje to samo, 814 01:07:29,260 --> 01:07:33,180 natomiast w przypadku drukowania wskaźnik stosunku adresem wskaźnika, 815 01:07:33,180 --> 01:07:36,010 jedno drukuje adres czego wskazując, 816 01:07:36,010 --> 01:07:40,360 Inne drukuje adresu wskaźnika na stosie. 817 01:07:40,360 --> 01:07:47,040 Można zmienić wskaźnik, nie można zmienić symbol tablicy. 818 01:07:47,740 --> 01:07:53,270 I wskaźnik sizeof będzie drukować wielkości tego typu wskaźnika. 819 01:07:53,270 --> 01:07:57,470 Więc int * p sizeof (p) będzie drukować 4, 820 01:07:57,470 --> 01:08:04,110 ale int tablica [5] print sizeof (array) będzie drukować 20. 821 01:08:04,110 --> 01:08:07,480 [Uczeń] Więc int tablica [5] będzie drukować 20? >> Tak. 822 01:08:07,480 --> 01:08:13,300 Dlatego wewnątrz buggy4 gdy kiedyś sizeof (tablica) 823 01:08:13,300 --> 01:08:16,660 to robi i <20, która nie jest, co chcieliśmy. 824 01:08:16,660 --> 01:08:20,880 Chcemy i <5. >> [Uczeń] Dobra. 825 01:08:20,880 --> 01:08:25,569 [Bowden], a następnie jak najszybciej rozpocząć przechodzącą w funkcji, 826 01:08:25,569 --> 01:08:34,340 gdybyśmy zrobili int * p = array; 827 01:08:34,340 --> 01:08:39,779 wewnątrz tej funkcji, możemy w zasadzie używać p oraz tablicę w dokładnie tych samych sposobów, 828 01:08:39,779 --> 01:08:43,710 oprócz problemu sizeof i problemu zmienia. 829 01:08:43,710 --> 01:08:49,810 Ale p [0] = 1; jest taka sama, jak mówi tablicy [0] = 1; 830 01:08:49,810 --> 01:08:55,600 I tak szybko, jak to mówimy foo (tablica) lub foo (p); 831 01:08:55,600 --> 01:08:59,760 wewnątrz foo funkcji, to jest dwa razy, to samo. 832 01:08:59,760 --> 01:09:03,350 Nie ma żadnej różnicy między tymi połączeniami. 833 01:09:07,029 --> 01:09:11,080 >> Wszyscy dobrze na tym? Okay. 834 01:09:14,620 --> 01:09:17,950 Mamy 10 minut. 835 01:09:17,950 --> 01:09:28,319 >> Postaramy się uzyskać w ramach tego programu Typer hakerów 836 01:09:28,319 --> 01:09:32,350 Ta strona, która ukazała się w zeszłym roku, czy coś. 837 01:09:34,149 --> 01:09:41,100 To jest po prostu być jak wpisać losowo i wypisze - 838 01:09:41,100 --> 01:09:46,729 Cokolwiek plik zdarza załadowany jest tym, co wygląda jak piszesz. 839 01:09:46,729 --> 01:09:52,069 To wygląda jak jakiś kod systemu operacyjnego. 840 01:09:53,760 --> 01:09:56,890 To, co chcemy realizować. 841 01:10:08,560 --> 01:10:11,690 Powinieneś mieć pliku wykonywalnego o nazwie hacker_typer 842 01:10:11,690 --> 01:10:14,350 że bierze w jednym argumentem, plik "typu hacker". 843 01:10:14,350 --> 01:10:16,480 Bieganie wykonywalny należy wyczyścić ekran 844 01:10:16,480 --> 01:10:20,850 a następnie wydrukować jeden znak z pliku przekazanego-w każdej chwili, gdy użytkownik naciśnie klawisz. 845 01:10:20,850 --> 01:10:24,990 Więc cokolwiek klawisz nacisnąć, należy wyrzucić i zamiast drukować znak z pliku 846 01:10:24,990 --> 01:10:27,810 to argument. 847 01:10:29,880 --> 01:10:34,350 Ja dość dużo powiedzieć, co te rzeczy Będziemy wiedzieć są. 848 01:10:34,350 --> 01:10:36,440 Ale chcemy, aby sprawdzić biblioteki termios. 849 01:10:36,440 --> 01:10:44,840 Nigdy nie używałem tej biblioteki w całym moim życiu, a więc ma bardzo minimalne cele. 850 01:10:44,840 --> 01:10:48,610 Ale to będzie biblioteka możemy użyć, aby wyrzucić charakter trafisz 851 01:10:48,610 --> 01:10:52,390 gdy piszesz do standardu w. 852 01:10:56,970 --> 01:11:05,840 Więc hacker_typer.c, a my będziemy chcieli # include. 853 01:11:05,840 --> 01:11:12,870 Patrząc na stronie podręcznika termios - jestem zgadywania w terminalu OS lub coś - 854 01:11:12,870 --> 01:11:16,240 I nie wiem, jak go odczytać. 855 01:11:16,240 --> 01:11:21,040 Patrząc na to, to mówi, aby objąć te 2 pliki, więc zrobimy to. 856 01:11:37,620 --> 01:11:46,820 >> Pierwszą rzeczą po pierwsze, chcemy podjąć w jednym argumentem, który plik należy otworzyć. 857 01:11:46,820 --> 01:11:52,420 Więc co chcę zrobić? Jak mogę sprawdzić, mam jeden argument? 858 01:11:52,420 --> 01:11:56,480 [Uczeń] Jeśli argc wynosi go. >> [Bowden] Tak. 859 01:11:56,480 --> 01:12:21,250 So if (argc = 2!) Printf ("Użycie:% s [file otworzyć]"). 860 01:12:21,250 --> 01:12:32,750 Więc teraz, jeśli to uruchomić bez podania argumentu - oh, potrzebuję nową linię - 861 01:12:32,750 --> 01:12:36,240 zobaczysz mówi usage:. / hacker_typer, 862 01:12:36,240 --> 01:12:39,770 a następnie drugi argument powinien być plik chcę otworzyć. 863 01:12:58,430 --> 01:13:01,260 Co mam teraz zrobić? 864 01:13:01,260 --> 01:13:08,490 Chcę, aby odczytać z tego pliku. Jak czytać z pliku? 865 01:13:08,490 --> 01:13:11,920 [Uczeń] go otworzyć pierwszy. >> Tak. 866 01:13:11,920 --> 01:13:15,010 Więc fopen. Co fopen wyglądać? 867 01:13:15,010 --> 01:13:22,980 [Uczeń] Filename. >> [Bowden] Filename będzie argv [1]. 868 01:13:22,980 --> 01:13:26,110 [Uczeń], a następnie to, co chcesz z tym zrobić, więc - >> [Bowden] Tak. 869 01:13:26,110 --> 01:13:28,740 Więc jeśli nie pamiętam, po prostu może zrobić fopen man, 870 01:13:28,740 --> 01:13:32,960 gdzie będzie const char * path, gdzie ścieżka jest nazwa pliku, 871 01:13:32,960 --> 01:13:34,970 const char * mode. 872 01:13:34,970 --> 01:13:38,660 Jeśli zdarzy się, nie pamiętam, co jest tryb, potem można szukać trybie. 873 01:13:38,660 --> 01:13:44,660 Wewnątrz stron podręcznika, znak ukośnika, co można użyć, aby szukać rzeczy. 874 01:13:44,660 --> 01:13:49,790 Więc wpisać / tryb wyszukiwania trybie. 875 01:13:49,790 --> 01:13:57,130 N i N są tym, co można wykorzystać, aby przejść przez mecze wyszukiwania. 876 01:13:57,130 --> 01:13:59,800 Tutaj mówi Argument mode wskazuje na łańcuch 877 01:13:59,800 --> 01:14:01,930 początku z jedną z następujących sekwencji. 878 01:14:01,930 --> 01:14:06,480 Więc r, Otwórz plik tekstowy do czytania. To, co chcemy zrobić. 879 01:14:08,930 --> 01:14:13,210 Do czytania, a ja chcę, aby zapisać, że. 880 01:14:13,210 --> 01:14:18,720 Rzeczą będzie plik *. Teraz to, co chcę zrobić? 881 01:14:18,720 --> 01:14:21,200 Daj mi sekundę. 882 01:14:28,140 --> 01:14:30,430 Okay. Teraz to, co chcę zrobić? 883 01:14:30,430 --> 01:14:32,940 [Student] Sprawdź, czy jest NULL. >> [Bowden] Tak. 884 01:14:32,940 --> 01:14:38,690 Za każdym razem, otworzyć plik, upewnij się, że jesteś z powodzeniem mógł go otworzyć. 885 01:14:58,930 --> 01:15:10,460 >> Teraz chcę zrobić to termios rzeczy tam, gdzie chcę, aby najpierw przeczytać moje aktualne ustawienia 886 01:15:10,460 --> 01:15:14,050 i uratować tych, w coś, to chcę, aby zmienić ustawienia 887 01:15:14,050 --> 01:15:19,420 wyrzucić dowolny znak i typ, 888 01:15:19,420 --> 01:15:22,520 a chcę zaktualizować te ustawienia. 889 01:15:22,520 --> 01:15:27,250 , A następnie na koniec programu, chcę wrócić do moich oryginalnych ustawień. 890 01:15:27,250 --> 01:15:32,080 Więc struct będzie z termios typu, i będę chciał dwa z nich. 891 01:15:32,080 --> 01:15:35,600 Pierwszy z nich będzie moje current_settings, 892 01:15:35,600 --> 01:15:42,010 i wtedy będziesz w moich hacker_settings. 893 01:15:42,010 --> 01:15:48,070 Po pierwsze, mam zamiar chcesz zapisać swoje bieżące ustawienia, 894 01:15:48,070 --> 01:15:53,790 potem zamierzam chcesz zaktualizować hacker_settings, 895 01:15:53,790 --> 01:16:01,570 a następnie drogą na końcu mojego programu, chcę wrócić do bieżących ustawień. 896 01:16:01,570 --> 01:16:08,660 Więc zapis aktualnych ustawień, sposób w jaki działa, mamy termios man. 897 01:16:08,660 --> 01:16:15,810 Widzimy, że mamy to, int int tcsetattr tcgetattr. 898 01:16:15,810 --> 01:16:22,960 I przechodzą w struct termios przez jego wskaźnik. 899 01:16:22,960 --> 01:16:30,640 Sposób to będzie wyglądać to - I've już zapomniał, co funkcja została wywołana. 900 01:16:30,640 --> 01:16:34,930 Skopiować i wkleić. 901 01:16:39,150 --> 01:16:45,500 Więc tcgetattr, to chcę przekazać w struct że jestem zapisywania informacji w, 902 01:16:45,500 --> 01:16:49,650 który będzie current_settings, 903 01:16:49,650 --> 01:16:59,120 i pierwszy argument jest deskryptor pliku dla rzeczy chcę zapisać atrybuty. 904 01:16:59,120 --> 01:17:04,360 Co deskryptor jest to jak każdym czasie otwierania pliku, pobiera deskryptor pliku. 905 01:17:04,360 --> 01:17:14,560 Kiedy fopen argv [1], to dostaje deskryptor pliku którego się odnosisz 906 01:17:14,560 --> 01:17:16,730 kiedy się chce czytać lub pisać. 907 01:17:16,730 --> 01:17:19,220 To nie deskryptor chcę użyć tutaj. 908 01:17:19,220 --> 01:17:21,940 Istnieją trzy deskryptory plikowe masz domyślnie, 909 01:17:21,940 --> 01:17:24,310 które są standardem, standard, i błąd standardowy. 910 01:17:24,310 --> 01:17:29,960 Domyślnie, myślę, że to standard w to 0, obecnie średnia to 1, błąd standardowy jest 2. 911 01:17:29,960 --> 01:17:33,980 Więc co chcę zmienić ustawienia? 912 01:17:33,980 --> 01:17:37,370 Chcę zmienić ustawienia, gdy uderzę znak, 913 01:17:37,370 --> 01:17:41,590 Chcę rzucić ten znak od zamiast wysyłać je na ekranie. 914 01:17:41,590 --> 01:17:45,960 Co stream - standard, standardowe wyjście lub błędu standardowego - 915 01:17:45,960 --> 01:17:52,050 reaguje na rzeczy, po wpisaniu na klawiaturze? >> [Uczeń] Standard widok >> Tak. 916 01:17:52,050 --> 01:17:56,450 Więc można albo zrobić 0 lub mogę stdin. 917 01:17:56,450 --> 01:17:59,380 Otrzymuję current_settings wzorca w. 918 01:17:59,380 --> 01:18:01,720 >> Teraz chcę, aby zaktualizować te ustawienia, 919 01:18:01,720 --> 01:18:07,200 więc najpierw ja skopiować do hacker_settings co moi current_settings są. 920 01:18:07,200 --> 01:18:10,430 A jak praca elemencie jest to po prostu skopiować. 921 01:18:10,430 --> 01:18:14,510 Spowoduje to skopiowanie wszystkich polach, jak można by oczekiwać. 922 01:18:14,510 --> 01:18:17,410 >> Teraz chcę zaktualizować niektóre pola. 923 01:18:17,410 --> 01:18:21,670 Patrząc na termios, trzeba by przeczytać wiele tego 924 01:18:21,670 --> 01:18:24,110 po prostu zobaczyć, co chcesz szukać, 925 01:18:24,110 --> 01:18:28,210 ale flagi Będziesz chcesz szukać to echo, 926 01:18:28,210 --> 01:18:33,110 tak ECHO znaków wejściowych Echo. 927 01:18:33,110 --> 01:18:37,710 Najpierw chcę ustawić - I've już zapomniał, co pola. 928 01:18:45,040 --> 01:18:47,900 To co struct wygląda. 929 01:18:47,900 --> 01:18:51,060 Więc tryby wprowadzania myślę, że chcemy zmienić. 930 01:18:51,060 --> 01:18:54,210 Przyjrzymy się w roztworze, aby upewnić się, że to, co chcemy zmienić. 931 01:19:04,060 --> 01:19:12,610 Chcemy zmienić lFlag w celu uniknięcia konieczności przejrzeć wszystkie te. 932 01:19:12,610 --> 01:19:14,670 Chcemy zmienić lokalne tryby. 933 01:19:14,670 --> 01:19:17,710 Trzeba by przeczytać cały ten rzeczy zrozumieć, gdzie wszystko należy 934 01:19:17,710 --> 01:19:19,320 że chcemy zmienić. 935 01:19:19,320 --> 01:19:24,120 Ale to jest w środku lokalnych trybach, gdzie mamy zamiar to zmienić. 936 01:19:27,080 --> 01:19:33,110 Więc hacker_settings.cc_lmode jest to, co się nazywa. 937 01:19:39,630 --> 01:19:43,020 c_lflag. 938 01:19:49,060 --> 01:19:52,280 To jest, gdy mamy do bitowe operatorów. 939 01:19:52,280 --> 01:19:54,860 Jesteśmy trochę z opóźnieniem, ale pojedziemy przez to bardzo szybko. 940 01:19:54,860 --> 01:19:56,600 To jest, gdy mamy do operatory bitowe, 941 01:19:56,600 --> 01:19:59,950 gdzie myślę, że jeden raz dawno temu, że przy każdym uruchomieniu czynienia z flagami, 942 01:19:59,950 --> 01:20:03,370 zamierzasz używać operatory bitowe dużo. 943 01:20:03,370 --> 01:20:08,240 Każdy bit odpowiada flaga jakiegoś zachowania. 944 01:20:08,240 --> 01:20:14,090 Więc tutaj, ta flaga ma kilka różnych rzeczy, gdzie wszystkie z nich oznacza coś innego. 945 01:20:14,090 --> 01:20:18,690 Ale to, co chcę zrobić, to wyłączyć bit odpowiadający ECHO. 946 01:20:18,690 --> 01:20:25,440 Tak, aby to wyłączyć zrobić & = ¬ ECHO. 947 01:20:25,440 --> 01:20:30,110 Właściwie myślę, że to jest jak techo czy coś. Idę sprawdzić ponownie. 948 01:20:30,110 --> 01:20:34,050 Mogę termios go. To tylko echo. 949 01:20:34,050 --> 01:20:38,440 ECHO będzie pojedynczy bit. 950 01:20:38,440 --> 01:20:44,230 ¬ ECHO będzie oznaczać wszystkie bity są ustawione na 1, co oznacza, że ​​wszystkie flagi są ustawione na true 951 01:20:44,230 --> 01:20:47,140 wyjątkiem bitu ECHO. 952 01:20:47,140 --> 01:20:53,830 Kończąc moje lokalnych flag z tym, to znaczy, wszystkie flagi, które są aktualnie ustawione na true 953 01:20:53,830 --> 01:20:56,520 wciąż będą ustawione na true. 954 01:20:56,520 --> 01:21:03,240 Jeśli moja flaga ECHO jest ustawiony na true, to jest koniecznie ustawić na false na flagę ECHO. 955 01:21:03,240 --> 01:21:07,170 Tak więc ta linia kodu po prostu wyłącza flagę ECHO. 956 01:21:07,170 --> 01:21:16,270 Pozostałe linie kodu, po prostu skopiuj je w interesie czasie, a następnie je wyjaśnić. 957 01:21:27,810 --> 01:21:30,180 W roztworze, mówi 0. 958 01:21:30,180 --> 01:21:33,880 To chyba lepiej, aby wyraźnie powiedzieć, stdin. 959 01:21:33,880 --> 01:21:42,100 >> Zauważ, że ja również robi echo | ICANON tutaj. 960 01:21:42,100 --> 01:21:46,650 ICANON odnosi się do czegoś, co oznacza oddzielną kanoniczny tryb. 961 01:21:46,650 --> 01:21:50,280 Co oznacza tryb kanoniczny zazwyczaj gdy piszesz z wiersza poleceń, 962 01:21:50,280 --> 01:21:54,670 standard nie przetwarza niczego aż trafisz linią. 963 01:21:54,670 --> 01:21:58,230 Więc kiedy się getString, wpisać kilka rzeczy, a potem trafisz linią. 964 01:21:58,230 --> 01:22:00,590 To jest, gdy jest wysłany do standardu w. 965 01:22:00,590 --> 01:22:02,680 To jest domyślna. 966 01:22:02,680 --> 01:22:05,830 Kiedy wyłączyć kanoniczny tryb, teraz każdy pojedynczy znak naciśnięciu 967 01:22:05,830 --> 01:22:10,910 jest to, co zostaje przetworzone, które jest zazwyczaj trochę zły, bo to wolno przetwarzać te rzeczy, 968 01:22:10,910 --> 01:22:14,330 dlatego dobrze jest go do bufora całych linii. 969 01:22:14,330 --> 01:22:16,810 Ale chcę, każdy znak do przetworzenia 970 01:22:16,810 --> 01:22:18,810 ponieważ nie ma to czekaj na mnie uderzyć newline 971 01:22:18,810 --> 01:22:21,280 przed przetwarza wszystkie znaki byłem pisania. 972 01:22:21,280 --> 01:22:24,760 To wyłącza kanoniczny tryb. 973 01:22:24,760 --> 01:22:31,320 Te rzeczy po prostu oznacza, podczas gdy w rzeczywistości przetwarza znaki. 974 01:22:31,320 --> 01:22:35,830 Oznacza to, przetwarzać je natychmiast, jak tylko piszę je, je przetwarzać. 975 01:22:35,830 --> 01:22:42,510 I jest to funkcja, która jest aktualizacją moje ustawienia do standardowych w, 976 01:22:42,510 --> 01:22:45,480 i środki TCSA zrobić to właśnie teraz. 977 01:22:45,480 --> 01:22:50,310 Inne opcje znajdują się czekać, aż wszystko, co jest obecnie w strumieniu jest przetwarzane. 978 01:22:50,310 --> 01:22:52,030 To naprawdę nie ma znaczenia. 979 01:22:52,030 --> 01:22:56,920 Wystarczy teraz zmienić moje ustawienia się, co jest obecnie w hacker_typer_settings. 980 01:22:56,920 --> 01:23:02,210 Chyba nazwał go hacker_settings, więc zmieńmy to. 981 01:23:09,610 --> 01:23:13,500 Zmień wszystko hacker_settings. 982 01:23:13,500 --> 01:23:16,870 >> Teraz na koniec naszego programu będziemy chcesz przywrócić 983 01:23:16,870 --> 01:23:20,210 tego, co jest obecnie wewnątrz normal_settings, 984 01:23:20,210 --> 01:23:26,560 który będzie po prostu wyglądać i normal_settings. 985 01:23:26,560 --> 01:23:30,650 Zauważ, że nie zmieniły się któryś z moich normal_settings od pierwotnie coraz to. 986 01:23:30,650 --> 01:23:34,520 Wtedy po prostu zmienić ich z powrotem, I przekazać je na końcu. 987 01:23:34,520 --> 01:23:38,390 To było aktualizacji. Okay. 988 01:23:38,390 --> 01:23:43,900 >> Teraz wewnątrz tutaj ja po prostu wyjaśnić kod w interesie czasie. 989 01:23:43,900 --> 01:23:46,350 To nie jest dużo kodu jest. 990 01:23:50,770 --> 01:24:03,750 Widzimy czytamy znak z pliku. Nazwaliśmy go f. 991 01:24:03,750 --> 01:24:07,850 Teraz możesz człowiek fgetc, ale jak fgetc zadziała 992 01:24:07,850 --> 01:24:11,910 jest po prostu to się zwracają znak, że po prostu czytać lub EOF, 993 01:24:11,910 --> 01:24:15,680 , co odpowiada w końcu lub jakiegoś happeningu pliku błędów. 994 01:24:15,680 --> 01:24:19,900 Jesteśmy zapętlenie, nadal odczytać pojedynczy znak z pliku, 995 01:24:19,900 --> 01:24:22,420 dopóki nie zabraknie znaków czytać. 996 01:24:22,420 --> 01:24:26,650 A gdy to robimy, że mamy czekać na pojedynczy znak ze standardowego w. 997 01:24:26,650 --> 01:24:29,090 Za każdym razem, wpiszesz coś w linii poleceń, 998 01:24:29,090 --> 01:24:32,820 że czyta się w postać z normą w. 999 01:24:32,820 --> 01:24:38,330 Następnie putchar właśnie zamiar umieścić char czytamy tutaj z pliku na wyjście standardowe. 1000 01:24:38,330 --> 01:24:42,890 Możesz człowiek putchar, ale to tylko wprowadzenie do standardu obecnie, to drukowanie ten znak. 1001 01:24:42,890 --> 01:24:51,600 Można też po prostu zrobić printf ("% c", c); sam pomysł. 1002 01:24:53,330 --> 01:24:56,670 Że zrobi większość naszej pracy. 1003 01:24:56,670 --> 01:25:00,300 >> Ostatnią rzeczą jaką będziesz chciał zrobić to właśnie fclose nasz plik. 1004 01:25:00,300 --> 01:25:03,310 Jeśli nie fclose, to jest wyciek pamięci. 1005 01:25:03,310 --> 01:25:06,680 Chcemy fclose plik pierwotnie otwarte i myślę, że to jest to. 1006 01:25:06,680 --> 01:25:13,810 Jeśli zrobimy, że ja już mam problemy. 1007 01:25:13,810 --> 01:25:17,260 Zobaczmy. 1008 01:25:17,260 --> 01:25:19,960 Jakie to narzekać? 1009 01:25:19,960 --> 01:25:30,220 Oczekiwano "int", ale argument jest typu "struct _IO_FILE * '. 1010 01:25:36,850 --> 01:25:39,370 Zobaczymy, czy to działa. 1011 01:25:45,210 --> 01:25:53,540 Dozwolone tylko w C99. Augh. Dobrze, aby hacker_typer. 1012 01:25:53,540 --> 01:25:57,760 Teraz mamy więcej przydatnych opisów. 1013 01:25:57,760 --> 01:25:59,900 Tak więc korzystać z nielegalnej identyfikator "normal_settings". 1014 01:25:59,900 --> 01:26:04,170 I nie nazywać normal_settings. Nazwałem to current_settings. 1015 01:26:04,170 --> 01:26:12,090 Więc zmieńmy wszystko. 1016 01:26:17,920 --> 01:26:21,710 Teraz przechodząc argument. 1017 01:26:26,290 --> 01:26:29,500 Zrobię to 0 do teraz. 1018 01:26:29,500 --> 01:26:36,720 Okay. . / Hacker_typer cp.c. 1019 01:26:36,720 --> 01:26:39,590 Też nie wyczyszczenie ekranu na początku. 1020 01:26:39,590 --> 01:26:42,960 Ale można spojrzeć do ostatniego zestawu problemów, aby zobaczyć, w jaki sposób wyczyścić ekran. 1021 01:26:42,960 --> 01:26:45,160 To tylko niektóre znaki drukowania 1022 01:26:45,160 --> 01:26:47,210 podczas gdy to robi to, co chcę zrobić. 1023 01:26:47,210 --> 01:26:48,900 Okay. 1024 01:26:48,900 --> 01:26:55,280 I myśląc o tym, dlaczego to musiał być 0 zamiast standardowego wejścia, 1025 01:26:55,280 --> 01:27:00,560 które należy # define 0, 1026 01:27:00,560 --> 01:27:03,890 narzeka, że ​​jest to - 1027 01:27:13,150 --> 01:27:19,360 Wcześniej, kiedy powiedziałem, że nie deskryptorów ale masz również swój plik *, 1028 01:27:19,360 --> 01:27:23,210 deskryptor pliku jest tylko jedna liczba całkowita, 1029 01:27:23,210 --> 01:27:26,970 natomiast * FILE ma całą masę rzeczy z nim związane. 1030 01:27:26,970 --> 01:27:30,380 Powodem trzeba powiedzieć 0 zamiast z stdin 1031 01:27:30,380 --> 01:27:37,480 jest to, że jest stdin * FILE, który wskazuje na tym co jest odsyłania deskryptor 0. 1032 01:27:37,480 --> 01:27:45,070 Więc nawet tutaj, gdy zrobić fopen (argv [1], Dostaję * plik z powrotem. 1033 01:27:45,070 --> 01:27:51,180 Ale gdzieś w tym FILE * jest rzeczą odpowiada deskryptor pliku dla tego pliku. 1034 01:27:51,180 --> 01:27:57,430 Jeśli spojrzeć na stronie man otwarte, więc myślę, że trzeba zrobić człowiek 3 open - nope - 1035 01:27:57,430 --> 01:27:59,380 man 2 open - tak. 1036 01:27:59,380 --> 01:28:06,250 Jeśli spojrzeć na strony dla otwarty, jest jak fopen niższym poziomie 1037 01:28:06,250 --> 01:28:09,350 i to wraca rzeczywistego deskryptora pliku. 1038 01:28:09,350 --> 01:28:12,050 fopen robi kilka rzeczy na górze otwarte, 1039 01:28:12,050 --> 01:28:17,640 który zamiast wrócić tylko, że deskryptor zwraca cały plik * wskaźnik 1040 01:28:17,640 --> 01:28:20,590 wewnątrz której nasza mała deskryptor. 1041 01:28:20,590 --> 01:28:25,020 Więc standard odnosi się do rzeczy * FILE, 1042 01:28:25,020 --> 01:28:29,120 natomiast 0 oznacza tylko normy deskryptora pliku w sobie. 1043 01:28:29,120 --> 01:28:32,160 >> Questions? 1044 01:28:32,160 --> 01:28:35,930 [Śmiech] Blew przez to. 1045 01:28:35,930 --> 01:28:39,140 Dobrze. Skończyliśmy. [Śmieje się] 1046 01:28:39,140 --> 01:28:42,000 >> [CS50.TV]