[Powered by Google Translate] [Odjeljak 5 - ugodnije]
[Rob Bowden - Sveučilište Harvard]
[Ovo je CS50. - CS50.TV]
>> Kao što sam rekao u mom e-pošte, postoji mnogo stvari koje možete koristiti
osim aparata da zapravo učiniti problematična seta.
Preporučujemo vam to učiniti u aparatu samo zato onda možemo lakše pomoći
i znamo kako će se sve raditi.
No, kao jedan primjer gdje možete učiniti stvari ako, recimo, nemate pristup
do aparata ili želite raditi u podrumu znanosti Center -
koji zapravo imaju aparat previše -
ako želite raditi bilo gdje.
Jedan primjer je što ste vidjeli / čuli SSH?
SSH je u osnovi samo kao povezivanje s nečim.
Zapravo, upravo sada sam SSHed u aparat.
Ja nikada ne rade izravno u aparat.
Ovdje je aparat, a ako pogledate dolje vidite ovu IP adresu.
Ja nikada ne rade u aparatu same;
Uvijek sam došao preko na iTerm2 prozora / terminalu prozora.
Možete SSH na tu IP adresu, ssh jharvard@192.168.129.128.
Sjećam se da je broj vrlo lako jer je tako lijepo uzorak.
Ali da će me pitati za moj lozinka, a sada sam u aparatu.
Uglavnom, u ovom trenutku, ako je otvorio terminal unutar aparata,
ovo sučelje, no što bi ga koristiti, je točno isti
kao sučelje Ja sam koristeći ovamo, ali sada ste SSHed.
Vi ne morate SSH na uređaj.
Jedan od primjera drugom mjestu ste mogli SSH na je prilično sam siguran da imaju po defaultu -
Oh. Veći.
Svi vi bi trebali imati po defaultu FAS računa o FAS poslužiteljima.
Za mene, ja bih SSH na rbowden@nice.fas.harvard.edu.
To će vas zatražiti da prvi put, a vi kažete da.
Moj lozinka samo će biti moj FAS lozinkom.
I tako sada, ja sam SSHed na lijepim poslužiteljima, a ja mogu učiniti ništa želim ovdje.
Puno klasa koje možete poduzeti, kao 124, će imati što upload stvari koje se ovdje
zapravo pošaljete svoje skupove problema.
Ali kažu da nemaju pristup vašem uređaju.
Zatim možete napraviti stvari, kao što je ovdje, to će reći -
Ovo je samo naš dio pitanja.
To će vas pitati da to učinite u aparatu.
Umjesto toga, ja ću samo to učiniti na poslužitelju.
Idem unzip to.
Problem će biti da ste navikli koristiti nešto poput gedit
ili bilo unutar uređaja.
Nećeš imati to na FAS poslužitelju.
To je sve samo će biti ovo tekstualno sučelje.
Tako da bi bilo jedan, pokušati naučiti tekst editor da oni imaju.
Oni imaju Nano.
Nano je obično prilično jednostavan za korištenje.
Možete koristiti svoje strijele i upišite obično.
Dakle, to nije teško.
Ako želite dobiti vrlo nestvarno možete koristiti Emacs,
koji se vjerojatno ne bi otvorio jer ja ne znam ni kako se zatvoriti Emacs.
Kontrola X, Kontrola C? Da.
Ili možete koristiti VIM, što je ono što sam koristiti.
I tako oni su vaše mogućnosti.
Ako ne želite da to učinite, možete također, ako pogledate manual.cs50.net--
Oh.
Na računalu, možete SSH pomoću Putty,
koje ćete morati preuzeti zasebno.
Na Mac, možete jednostavno po defaultu korištenja terminala ili možete preuzeti iTerm2,
koji je kao lijepo, fancy Terminal.
Ako idete na manual.cs50.net vidjet ćete link na Notepad + +,
što je ono što se može koristiti na računalu.
To vam omogućuje da SFTP iz Notepad + +, koji je u osnovi SSH.
Što će to neka ti je urediti svoje datoteke na lokalnoj razini,
i onda kad god želite da ih spasi, ona će vas spasiti da nice.fas,
gdje onda možete ih izvoditi.
A ekvivalent na Mac će biti TextWrangler.
Dakle, to vam omogućuje da učinite istu stvar.
To vam omogućuje uređivanje datoteke na lokalnoj razini, te ih spremiti na nice.fas,
gdje onda možete ih izvoditi.
Dakle, ako ste ikada zapeli bez aparata, imate ove opcije
na dalje raditi svoje skupove problema.
Jedan problem će biti da nećeš imati CS50 knjižnicu
jer nice.fas ne po defaultu imaju to.
Možete preuzeti CS50 knjižnicu -
Ja ne mislim da je potrebno da u ovom trenutku.
Možete preuzeti CS50 knjižnicu i kopirati ga preko nice.fas,
ili mislim u ovom trenutku ne koristite ga više svejedno.
Ili, ako ćemo učiniti, možete za sada ga zamijeniti s
je implementacija funkcija u CS50 knjižnici svejedno.
Tako da ne bi trebalo biti da je mnogo ograničenja.
I to je to.
>> Ja ću se vratiti na aparatu sada, a mi ćemo učiniti sve što je u aparatu.
Gledajući na našem dijelu pitanja, na početku, kao što sam rekao u mom e-pošte,
moramo razgovarati o jednom kratkom li su se trebali gledati.
Imamo preusmjeravanje & cijevi i ova tri pitanja.
>> Za koji potok ne funkcionira kao printf pisati po defaultu?
Dakle potok. Što je struja?
Stream je u osnovi kao da je to samo neke od njih -
To nije ni izvor 1s i 0s.
Struja to je molba za ovdje je standardni van.
I tako standardni izlaz je potok da kada pišete na njega,
se pojavljuje na zaslonu.
Standardni van, tako potoka, to znači da samo napisati 1s i 0s na njega,
a drugi kraj standardni izlaz samo čita iz tog potoka.
To je samo niz 1s i 0s.
Možete pisati potoka ili možete pročitati iz potoka
ovisno o tome što je zapravo potok.
Druge dvije zadane struje su standardni u i standardnom pogreškom.
Standard u je kad god ne GetString, to je za vas čeka na ulaz stvari.
Tako je za vas čeka, to je zapravo čeka na standard u,
što je zapravo ono što ste dobili kad upišete na tipkovnici.
Vi pišete u standardu u.
Standardna pogreška je u osnovi jednak standardnom van,
ali to je specijalizirana za koje prilikom ispisa na standardne pogreške,
ti si trebao samo ispisati poruku o pogrešci na to
tako da možete razlikovati redovitim porukama ispisanim na zaslonu
u odnosu na pogreškama, ovisno o tome da li su otišli na standardni izlaz ili standardne pogreške.
Datoteke previše.
Standardni van, standard u, a standardna pogreška su samo posebni potoci,
ali stvarno bilo koju datoteku, kada otvorite datoteku, ona postaje tok bajtova
gdje možete samo pročitati iz tog potoka.
Vi, za najveći dio, mogu samo zamisliti datoteku kao tok bajtova.
Dakle, ono što potoci oni pisati po defaultu? Standardni van.
>> Koja je razlika između> i >>?
Je li itko gledati video unaprijed? Ok.
> Će biti kako se preusmjeriti na datoteke,
i >> također će se preusmjeriti izlaz u datoteke,
ali umjesto toga će se dodati u datoteku.
Na primjer, recimo da sam se dogoditi da imaju DICT ovdje,
i samo stvari unutar DICT je mačka, mačka, pas, riba, pas.
Jedna naredba da imate na naredbenog retka je mačka,
koji je pravedan idući ispisati ono što je u datoteci.
Dakle, kada kažem mačka dict, to će ispisati mačka, mačka, pas, riba, pas. To je sve što mačka radi.
To znači da je tiskana na standard od mačka, mačka, pas, riba, pas.
Ako sam umjesto želite preusmjeriti da u datoteku, mogu koristiti> i to preusmjeriti na ono što je datoteka.
Nazvat ću datoteku datoteka.
Pa sad, ako ja li, vidjet ću imam novu datoteku pod nazivom datoteke.
I ako sam ga otvoriti, to će imati točno ono što mačka staviti na naredbenog retka.
Pa sad, ako sam to učiniti opet, onda će preusmjeriti izlaz u datoteku,
i ja ću imati istu točno stvar.
Dakle, tehnički, to je potpuno overrode ono što smo imali.
A vidjet ćemo, ako sam promijeniti dict, sam izvadio psa.
Sada, ako mi mačka dict u datoteci opet, idemo imate novu verziju s pas uklonjen.
Tako da ga potpuno nadjačava.
Umjesto toga, ako koristite >>, to će dodati datoteke.
Sada, otvaranje datoteka, vidimo imamo samo dva puta istu stvar tiskani
jer je to bio tamo jednom, onda smo u prilogu izvornika.
Dakle, to je ono što> i >> napraviti.
Da li sljedeći pitati - To ne pita o tome.
>> Drugi koji imamo je <, koji, ako> preusmjerava standardni out,
<Će se preusmjeriti standarda u.
Idemo vidjeti ako imamo primjer.
Ja mogu napisati jedan pravi brzo.
Uzmimo bilo koju datoteku, hello.c.
Relativno jednostavan datoteka.
Ja sam samo dobivanje string, a zatim ispis "Hello" bez obzira na niz Upravo sam ušao bio.
Tako bi pozdraviti i onda. / Bok.
Sada me je navelo da unesete nešto,
što znači da je čeka na stvari koje se upisuju u standardu u.
Tako unijeti što god želim u standardu u. Mi samo htio reći Pozdrav, Rob!
Onda to znači tiskanje standardu iz Pozdrav, Rob!
Ako mi je činiti. / Bok, a zatim preusmjeravanje,
za sada se samo može preusmjeriti iz datoteke.
Dakle, ako sam stavio u neki file, txt, a ja sam stavio Rob,
ako sam pokrenuti bok, a zatim preusmjeriti datoteku txt u. / halo, to će reći Pozdrav, Rob! odmah.
Kada je prvi dobiva GetString i to čeka na standardu u,
standard u više ne čeka na tipkovnici podataka da biste ušli.
Umjesto toga, mi smo preusmjereni standard u čitati iz datoteke txt.
I tako to ide čitati iz datoteke txt, što je samo linija Rob,
i onda će se ispisati Hello, Rob!
A ako sam htio, mogao učiniti. / Pozdrav <txt
i onda standardno se da je tisak, koji je Hello, Rob!,
Ja mogu preusmjeriti da u vlastitu datoteku.
Samo ću nazvati datoteku halo - ne, neću, jer to je izvršna - txt2.
Sada, txt2 će imati izlaz. / Hello <txt, što će biti Pozdrav, Rob!
>> Pitanja?
>> Ok. Dakle ovdje imamo plinovoda.
Cijevi su zadnja jedinica preusmjeravanje.
>> Oh. Valjda još jedan jedinica preusmjeravanje je ako umjesto> ti 2>,
da je preusmjeravanje standardnu ​​pogrešku.
Dakle, ako je nešto pošlo za standardne pogreške, da ne bi dobili staviti u txt2.
Ali primijetite da radim 2>, onda je to još uvijek ispisa Pozdrav, Rob! na naredbenog retka
jer ja sam samo preusmjeravanje standardnu ​​pogrešku, nisam preusmjeravanje standarda van.
Standardna pogreška i standardno se razlikuju.
Ako biste željeli zapravo pisati standardne pogreške,
onda bih mogao promijeniti to biti fprintf na stderr.
Dakle printf, po defaultu, ispisuje na standardni izlaz.
Ako želim ispisati na standardne pogreške ručno, onda moram koristiti fprintf
i odrediti ono što želim za ispis.
Ako umjesto toga sam učinio fprintf stdout, onda je to u osnovi ekvivalent printf.
Ali fprintf za standardne pogreške.
Pa sad, ako sam preusmjeriti to u txt2, Pozdrav, Rob! još uvijek uzimajući tiskan na naredbenog retka
jer to je dobivanje tiskan na standardne pogreške, a ja sam samo preusmjeravanje standarda van.
Ako ja sada preusmjeriti standardnu ​​pogrešku, sada se nije tiskan, a txt2 će biti Pozdrav, Rob!
Tako sada, možete ispisati svoje stvarne pogreške na standardnom pogreškom
i ispisati svoje redovite poruke na standardni izlaz.
I tako kada pokrenete program, možete ga pokrenuti kao. / Pozdrav ovu vrstu s 2>
tako da vaš program će se pokrenuti normalno,
ali sve poruke o pogreškama koje ste dobili možete provjeriti kasnije u svom dnevniku pogreške,
tako pogrešaka, a zatim gledati kasnije i vaš pogreške datoteka će imati bilo kakve pogreške koje su se dogodile.
>> Pitanja?
>> Posljednji je cijev koja možete razmišljati kao vodeći standard iz jedne naredbe
a što je standard u za sljedeću naredbu.
Primjer ovdje je odjek je stvar naredbenog retka
samo da se ide na odjek god sam stavio kao argument. Neću staviti citati.
Echo bla, bla, bla, samo će se ispisati bla, bla, bla.
Prije, kad sam rekao da sam ja morao staviti Rob u txt datoteku
jer ja samo mogu preusmjeriti txt datoteke, umjesto toga, / ako sam jeka Rob
i onda ga u cijevi. / halo, koji će također učiniti istu vrstu stvar.
To je uzimanje izlaz ove naredbe, jeka Rob,
i koristiti ga kao ulaz za. / bok.
Možete misliti o njemu kao prvo preusmjeravanje echo Rob u datoteku
i onda ulaz u. / halo tu datoteku koja je upravo outputted.
Ali to traje privremenu datoteku iz slike.
>> Pitanja o tome?
>> Sljedeće pitanje će uključivati ​​ovo.
Što Plinovod bi mogao koristiti kako bi pronašli broj jedinstvenih imena u datoteci pod nazivom names.txt?
Naredbe Mi ćemo želite koristiti ovdje su jedinstveni, tako uniq, a zatim wc.
Možete napraviti čovjek uniq zapravo pogledati što da radi,
i to samo ide za filtriranje susjedne podudaranje linije od ulaza.
I čovjek wc ide za ispis newline, riječi i bajtova za svaku datoteku.
I posljednji idemo želite koristiti je vrsta,
koji će se samo sortiranje linije txt datoteku.
Ako sam napraviti neki txt, names.txt, i to je Rob, Tommy, Josip, Tommy, Josip, RJ, Rob,
ono što želim učiniti ovdje je pronaći broj jedinstvenih imena u ovoj datoteci.
Dakle, ono što bi trebao biti odgovor? >> [Student] 4. >> Da.
To bi trebao biti 4 od Rob, Tommy, Josipa, RJ su jedina jedinstvena imena u ovoj datoteci.
Prvi korak, ako sam to riječ računati na names.txt,
to je zapravo govori mi sve.
To je zapravo tisak - neka se vidi, čovjek wc - nove linije i dr., riječi i bajt count.
Ako sam samo stalo linije, onda ja samo mogu učiniti wc-l names.txt.
Dakle, to je korak jedan.
Ali ja ne želim da wc-l names.txt jer names.txt samo sadrži sva imena,
i želim da filtrira sve ne-jedinstvene one.
Dakle, ako sam to uniq names.txt, da ne sasvim mi dati ono što želim
jer su dvostruki imena su još uvijek tamo.
Zašto je to? Zašto je uniq ne radi ono što želim?
[Student] U duplikati nisu [nečujno] >> Da.
Zapamtite man stranicu za uniq kaže filter susjedna podudarna linije.
Oni nisu u susjedstvu, tako da ih neće filtrirati.
Ako sam ih poredate prvi, vrsta names.txt će staviti sve duple linije zajedno.
Tako sada vrsta names.txt je to.
Idem želite koristiti kao ulaz na uniq, koji je | uniq.
To mi daje Josipu, RJ, Rob, Tommy,
i želim ga koristiti kao ulaz u wc-l,
koji će mi dati četiri.
Kao da kaže ovdje, ono plinovod mogao koristiti?
To možete učiniti mnogo stvari poput korištenja niz naredbi
gdje ćete koristiti izlaz iz jedne naredbe kao ulaz na sljedeću naredbu.
Možete učiniti puno stvari, puno pametnih stvari.
>> Pitanja?
Ok.
To je to za cijevi i preusmjeravanje.
>> Sada ćemo ići na stvarne stvari, kodiranje stvari.
Unutar ovaj PDF, vidjet ćete ovu naredbu,
i da ćete želite pokrenuti ovu naredbu u vašem uređaju.
wget je naredba za samo dobivanje nešto s interneta, u osnovi,
tako wget i ovaj URL.
Ako ode na ovaj URL u pregledniku, to bi preuzeti tu datoteku.
Upravo sam kliknuo na njega, tako da preuzmete datoteku za mene.
Ali pisanje wget te stvari unutar terminala
samo ide ga preuzeti na svoj terminal.
Imam section5.zip, a vi ćete želite unzip section5.zip,
koji će vam dati mapu pod nazivom section5,
koji će imati sve datoteke idemo da se pomoću danas unutar nje.
Kao ovi programi "datoteka imena sugeriraju, oni su malo lud,
tako da vaš zadatak je shvatiti zašto koristite gdb.
Da li svatko ima ih skinuti / znati kako bi ih preuzeli
u svojoj aparat? Ok.
>> Trčanje ./buggy1, to će reći segmentacije grešku (jezgra bačena),
koji svaki put kada se segfault, to je loša stvar.
Pod kojim okolnostima ne dobijete segfault?
[Student] Dereferencing null pokazivač. >> Da. Dakle, to je jedan primjer.
Dereferencing null pokazivač idete da biste dobili segfault.
Što znači segfault je god dira memoriju da ne bi trebali biti dira.
Dakle dereferencing null pokazivač dodiruje adresu 0,
i zapravo, sva računala danas kažu da je adresa 0 je memorija koju ne treba dira.
Dakle, to je razlog zašto dereferencing null pointer rezultate u segfault.
Kada vam se dogoditi da ne inicijalizirati pokazivač, onda to ima smeća vrijednost,
pa kada pokušate dereference to, po svemu sudeći ste dira memoriju
koji je u sredini nigdje.
Ako vam se dogoditi da se posreći i smeća vrijednost
dogodilo ukazati na negdje na stogu ili nešto,
onda kada dereference da pokazivač koji niste inicijaliziran,
ništa neće poći po zlu.
No, ako je pokazujući na, recimo, negdje između dimnjaka i gomile,
ili to pokazuje samo negdje da nije bio korišten od strane svog programa, ali,
onda ste dira memoriju da ne bi trebali biti dodirivanje i segfault.
Kada napisati rekurzivni funkciju i to recurses previše puta
i vaš stog raste prevelika i slagati sudara u stvari
da to ne bi trebao biti sudara s, ti si dira memoriju da ne bi trebali biti dira,
tako da segfault.
To je ono što segfault je.
>> To je također isti razlog da, ako imate niz poput -
Vratimo se na prethodni program.
U hello.c--Ja sam samo će učiniti nešto drugo.
char * s = "Hello World!";
Ako sam koristiti * s = nešto ili s [0] = 'X';
tako da bi halo,. / halo, zašto da segfault?
Zašto to segfault?
Što bi vi očekujete da će se dogoditi?
Ako sam printf ("% s \ n", a); što bi vi očekujete da će se ispisati?
[Student] X bok. >> Da.
Problem je u tome da kada se proglasi string ovako,
a je pokazivač koji će ići na stog,
i ono što je ukazuje na to je niz koji je sadržan u samo za čitanje memorije.
Dakle, samo po imenu, samo za čitanje memorije, te bi trebao dobiti ideju
da, ako pokušate promijeniti ono što je samo za čitanje memorije,
radite nešto što ne bi trebao biti događaj s pamćenjem i segfault.
To je zapravo velika razlika između char * s, a char s [].
Dakle char s [], sada ovaj niz će se staviti na stog,
i stog nije samo za čitanje, što znači da bi to trebalo raditi savršeno u redu.
I to radi.
Zapamtite da kada radim char * s = "Hello World!", A sama je na stogu
ali s točke na negdje drugdje, a da negdje drugdje dogodi da se samo za čitanje.
Ali char s [] je samo nešto na stog.
Dakle, to je još jedan primjer segfault događa.
>> Vidjeli smo da je ./buggy1 rezultiralo segfault.
U teoriji, da ne bi trebali gledati na buggy1.c odmah.
Umjesto toga, mi ćemo gledati na to kroz gdb.
Primijetit ćete da kada se segmentacije grešku (jezgra bačena),
ste dobili ovu datoteku ovamo zove jezgre.
Ako smo ls-l, vidjet ćemo da je jezgra je obično prilično velika datoteka.
To je broj bajtova u datoteci, tako da izgleda kao da je 250 i nešto kilobajta.
Razlog za to je da je ono što je srž deponij zapravo je
kada je vaš program ruši, stanje memorije vašeg programa
samo dobiva kopirati i zalijepiti u ovoj datoteci.
Ona dobiva bačena u toj datoteci.
Ovaj program, a to je trčanje, dogodilo da su memorije od oko 250 kilobajta,
pa to je ono što je dobio bačena u ovoj datoteci.
Sada možete gledati na tu datoteku, ako mi GDB buggy1 jezgru.
Mi samo možemo učiniti gdb buggy1, i da će samo pokrenuti gdb redovito,
pomoću buggy1 kao ulazne datoteke.
Ali ako ne GDB buggy1 jezgru, onda je to posebno će se pokrenuti gdb
gledanjem na toj jezgri datoteke.
I rekavši buggy1 znači gdb zna da je jezgra datoteku dolazi iz buggy1 programa.
Dakle gdb buggy1 jezgra će odmah donijeti nam
na kojem je program dogodilo prekinuti.
Ovdje vidimo program prestaje sa signalom 11, Segmentacija kvara.
Mi se dogoditi da vidi liniju skupštine, koja vjerojatno nije vrlo korisno.
Ali ako upišete BT ili Povratno praćenje, koji će biti funkcija
koji nam daje popis naših trenutnih stog okvire.
Dakle povratno praćenje. Izgleda imamo samo dva dimnjaka okvire.
Prvi je naš glavni stog okvir,
a drugi je stog okvir za ovu funkciju da mi se dogoditi da se u,
koji izgleda kao imamo samo sklopa kod za.
Dakle, vratimo se u našem glavnom funkcijom,
i da to možemo učiniti okvir jedne, i mislim da možemo napraviti prema dolje,
ali ja gotovo nikad ne dolje - ili gore. Da.
Gore i dolje. Gore vam donosi jednu stog okvir, dolje vam donosi niz stog okvir.
I imaju tendenciju da nikada koristiti.
Upravo sam konkretno reći okvir 1, koji se ići na okvir s oznakom 1.
Okvir 1 će nas dovesti u glavnom stog okvir,
i to kaže ovdje liniju koda mi se dogoditi da se na.
Ako smo htjeli još par linija koda, možemo reći popis,
i da će nam dati sve linije koda oko nje.
Linija mi segfaulted na bilo 6:
if (strcmp ("CS50 stijene", argv [1]) == 0).
Ako to nije očito još, možete ga dobiti ravno iz ovdje samo razmišljam zašto segfaulted.
No, možemo ga uzeti jedan korak dalje i reći: "Zašto bi argv [1] segfault?"
Idemo ispis argv [1], i to izgleda kao da je 0x0, koji je null pokazivač.
Mi smo strcmping CS50 stijene i Null, i to tako da će segfault.
I zašto je argv [1] null?
[Student] Zato mi nije dao nikakve ga naredbenog retka argumente.
Da. Nismo mu dati nikakve naredbenog retka argumente.
Dakle ./buggy1 samo će imati argv [0] biti ./buggy1.
To neće imati argv [1], tako da će segfault.
Ali ako, umjesto toga, radim samo CS50, to će reći ćete dobiti D
jer to je ono što je trebao učiniti.
Gledajući buggy1.c, to je trebalo ispisati "Ti dvojku" -
Ako argv [1] nije "CS50 stijene", "Ti dvojku", drugi "Možete dobiti!"
Dakle, ako želimo, trebamo to usporediti kao istinito,
što znači da je to uspoređuje s 0.
Dakle, argv [1] treba biti "CS50 stijene".
Ako želite to učiniti na naredbenog retka, morate koristiti \ pobjeći prostor.
Dakle CS50 \ stijene i dobijete A!
Ako to ne učinite crticu, zašto to ne rade?
[Student] To je dvije različite argumente. >> Da.
Argv [1] će biti CS50 i argv [2] koja će se stijene. Ok.
>> Sada ./buggy2 će segfault opet.
Umjesto otvarajući ga sa svojim osnovnim datoteku, samo ćemo otvoriti buggy2 izravno,
tako gdb buggy2.
Sada, ako smo samo pokrenuti naš program, onda će to reći Program dobio signal SIGSEGV,
koji je segfault signal, a to je mjesto gdje se to dogodilo da se dogodi.
Gledajući naše Povratno praćenje, vidimo da smo bili u funkciji oh_no,
koji je pozvao funkciju Dinky, koji je bio pozvan od strane funkcije binky,
koji je pozvao glavni.
Također možemo vidjeti argumente za ove funkcije.
Argument da Dinky i binky bio jedan.
Ako ćemo navesti funkcije oh_no, vidimo da oh_no samo radi char ** S = NULL;
* S = "BOOM";
Zašto bi to uspjeti?
[Student] Vi ne možete dereference nul pokazivač? >> Da.
To samo govori a je NULL, bez obzira na to, ako se to dogodi biti char **,
koji, ovisno o tome kako ga tumače, to bi mogao biti pokazivač na pokazivač na niz
ili niz žice.
To je i je NULL, pa * s je dereferencing null pokazivač,
i tako to ide na sudar.
To je jedan od najbržih načina možete eventualno segfault.
To je samo proglašenje null pokazivač i odmah segfaulting.
To je ono što oh_no radi.
Ako ćemo ići gore jedan okvir, onda ćemo ući u funkciju koja se zove oh_no.
Moram to učiniti dolje.
Ako ne unesete naredbu, a vi samo pritisnite Enter opet,
samo će ponoviti prethodne naredbe koje ste pokrenuli.
Mi smo u okviru jedne.
Oglas tog okvira, vidimo ovdje je naša funkcija.
Možete pogoditi popis opet, ili možete napraviti popis 20 i on će se popis više.
Funkcija nakićen kaže ako je i jedan, a zatim otići na oh_no funkciji,
drugdje ići na graciozan funkciji.
A znamo i iznosi 1 jer mi se dogoditi da vidim ovdje
da nakićen zvao s argumentom jedan.
Ili možete jednostavno moram ispisati i to će reći da sam je jednom.
Mi smo trenutno u Dinky, a ako odemo još jedan okvir, znamo da ćemo završiti u binky.
Gore. Sada smo u binky.
Oglas ovu funkciju - popis od prije polovine me satre -
ona je započela kao da sam je 0, onda ćemo ga nazvati oh_no, drugačije nazvati nakićen.
Znamo bio sam jednom, tako se zove nakićen.
I sad smo se vratili u glavni, a glavna samo će biti int i = rand ()% 3;
To samo će vam dati slučajni broj koji je bilo 0, 1 ili 2.
To će se zvati binky s tim brojem, a to će se vratiti 0.
Gledajući to,
samo hodanje kroz program ručno bez trčanje odmah,
ti bi postavili break na glavnom, što znači da kada smo pokrenuti program
vaš program radi dok ne udari break.
Dakle pokretanja programa, ona će se izvoditi i onda će pogoditi glavnu funkciju i prestati prikazivati.
Sada smo unutar glavna, i korak ili sljedećeg će nas dovesti do sljedećeg retka koda.
Možete napraviti korak ili sljedeći.
Udaranje sljedeći, sada sam je postavljen na rand ()% 3, tako da možemo ispisati vrijednost i,
a to će reći da sam je jednom.
Sada to ne obzira da li možemo koristiti sljedeći korak ili.
Mislim da je važno u prethodnom jedan, ali mi bi željeli koristiti sljedeći.
Ako ćemo koristiti korak, stupamo u funkciju, što znači pogledati na stvar
što se događa unutar binky.
Ako koristite sljedeći, onda to znači ići preko funkciju
i samo ići na sljedeći redak koda u našem glavnom funkciji.
Upravo ovdje na ovoj liniji, bio sam u kojem je rekao rand ()% 3;
ako sam učinio korak, to će ići u provedbu rand
i pogledati što se događa tamo, a ja sam mogao proći kroz rand funkcije.
Ali ja ne stalo rand funkcije.
Ja samo želim ići na sljedeći redak koda u glavnom, pa sam koristiti sljedeći.
Ali sada imam brigu o binky funkciju, pa želim da korak u tome.
Sada sam u binky.
Prva linija koda će reći ako (i == 0), sam uzeti jedan korak,
vidimo se završiti na Dinky.
Ako smo popis stvari, vidjet ćemo da je to provjerio je i = 0.
i je nije jednaka 0, tako da ode u drugo stanje,
koji će se nazvati Dinky (i).
Možda se zbuniti.
Ako samo pogledate ovih redaka izravno, možda mislite da ako (i == 0),
ok, onda sam uzeo korak i sada sam na Dinky (i),
možda mislite da mora značiti i = 0 ili nešto.
Ne, to samo znači da se zna da može staviti izravno na liniji Dinky (i).
Jer ja ne 0, sljedeći korak ne ide do kraja u drugi.
Inače nije linija će to zaustaviti na.
To je samo ići na sljedeći redak to zapravo može realizirati, što je nakićen (ja).
Ulazeći u Dinky (ja), vidimo ako (i == 1).
Mi ne znamo i = 1, pa kad smo korak, znamo da ćemo završiti u oh_no
jer sam = 1 naziva funkcije oh_no, koju može stati u,
koja će se postaviti char ** s = na NULL i odmah "bum".
I onda zapravo gleda na provedbi buggy2,
to, ja samo dobivanje slučajni broj - 0, 1, ili 2 - poziv binky,
što ako ja je 0 to zove oh_no, inače naziva nakićen, koji dolazi ovdje.
Ako sam je jednom, poziv oh_no, drugačije nazvati graciozan, koji dolaze ovdje,
ako je i 2, nazovite oh_no.
Ja čak ne mislim da postoji način -
Da li itko vidi način izrade ovaj program koji neće segfault?
Jer ako sam nešto nedostaje, ako je i 0, odmah ćete segfault,
drugo idete u funkciji što ako sam je jednom ste segfault,
drugo idete u funkciji gdje ako je i dvije ste segfault.
Dakle, bez obzira što radite, segfault.
>> Valjda jedan način popravljajući to će biti umjesto da radiš char ** S = NULL,
mogli malloc prostor za taj niz.
Mogli smo učiniti malloc (sizeof) - sizeof što?
[Student] (char) * 5? >> Da li to činiti zar ne?
Ja sam uz pretpostavku da će raditi ako sam ga zapravo trčao, ali to nije ono što ja tražim.
Pogledajte vrsti s.. Dodajmo int *, tako int * x.
Ja bih to malloc (sizeof (int)).
Ili, ako sam htio niz 5, ja bih to (sizeof (int) * 5);
Što ako imam int **?
Što bih malloc?
[Student] Veličina pokazivača. >> Da. (Sizeof (int *));
Ista stvar ovdje dolje.
Želim (sizeof (char *));
To će se alocirati prostor za pokazivač koji upućuje na "bum".
Ne trebam izdvojiti prostor za "bum" sama
jer je to u osnovi ekvivalent onoga što sam rekao prije
od char * x = "BOOM".
"BOOM" već postoji. To se događa da postoje u read-only regiji memorije.
Ali to već postoji, što znači ovaj redak koda, ukoliko je char **,
onda * s je char * i da postavljate ovu char * ukazati na "bum".
Ako sam htjela kopirati "boom" u s., onda bih morati izdvojiti prostor za s..
Učinit ću * s = malloc (sizeof (char) * 5);
Zašto pet?
Zašto ne 4? To izgleda kao "boom" 4 znaka. >> [Student] null karakter.
Da. Sve svoje žice će trebati null karakter.
Sada ja mogu učiniti nešto poput strcat - Što je funkcija za kopiranje niz?
[Student] KPJ? >> Strcpy.
Čovjek strcpy.
Dakle strcpy ili strncpy.
strncpy je malo sigurnije jer možete odrediti točno koliko znakova,
ali ovdje to ne smeta, jer mi znamo.
Dakle strcpy i gledati u argumente.
Prvi argument je naše odredište.
Drugi argument je naš izvor.
Mi idemo kopirati u našem mjestu * S pokazivač "bum".
Zašto bi želite učiniti sa strcpy umjesto samo ono što smo imali prije
od * s = "BOOM"?
Tu je razlog možda želite to učiniti, ali što je to razlog?
[Student] Ako želite nešto promijeniti u "boom". >> Da.
Sada mogu učiniti nešto slično s [0] = 'X';
jer s točke na hrpu i da je prostor na hrpi koja je okrenuta prema
je pokazivač više prostora na hrpu, koja je čuvanje "bum".
Dakle, ovaj primjerak "boom" koji se pohranjuju u gomili.
Postoje tehnički dvije kopije "bum" u našem programu.
Tu je prvi onaj koji je samo dao ovaj "bum" string konstante,
a drugi primjerak "boom", strcpy stvorio primjerak "bum".
Ali primjerak "boom" koji se spremaju na hrpi, i hrpa ste slobodni promijeniti.
Gomila ne samo za čitanje, tako da znači da je [0]
će vam promijeniti vrijednost "bum".
To će vam promijeniti te znakove.
>> Pitanja?
Ok.
>> Premještanje na buggy3, ajmo GDB buggy3.
Mi samo ga pokrenuti, a vidimo što smo dobili segfault.
Ako povratno praćenje, postoje samo dvije funkcije.
Ako idemo u našem glavnom funkcijom, vidjet ćemo da smo segfaulted na toj liniji.
Dakle, samo gleda na toj liniji, za (int redak = 0; fgets ove stvari ne jednak NULL;
linija + +).
Naša prethodna okvir zvao _IO_fgets.
Vidjet ćete da je puno s ugrađenim u C funkcija,
da kad ste dobili segfault, tu će biti jako grobni imena funkcija
kao što je ovaj _IO_fgets.
No, to će se odnositi na ovom fgets poziva.
Negdje u ovdje, mi smo segfaulting.
Ako gledamo argumenata za fgets, možemo ispisati tampon.
Ajmo ispisati - Oh, ne.
Ispis se ne ide na posao točno onako kako želim da.
Pogledajmo stvarni programa.
Pufer je lik polje. To je lik niz od 128 znakova.
Dakle, kada kažem ispis tampon, to će ispisati one 128 znakova,
koja valjda je ono što se očekuje.
Ono što sam bio u potrazi za je ispisati adresu tampon,
ali to zapravo ne da mi puno.
Dakle, kada sam se dogoditi da kažu ovdje x tampon, to mi pokazuje 0xbffff090,
koja, ako se sjećate iz ranije ili nekom trenutku, Oxbffff tendira da bude stog-ish regija.
Stog sklon početi negdje samo pod 0xc000.
Samo gledajući ovu adresu, znam da tampon se događa na stog.
Ponovno moj program, trčanje, gore, tampon smo vidjeli bio ovaj slijed znakova
da su prilično besmisleno.
Zatim ispis datoteke, što znači datoteka izgledati?
[Student] Null. >> Da.
Datoteka je tipa FILE *, tako da je pokazivač,
i vrijednost tog pokazivača null.
Dakle fgets će pokušati pročitati iz tog pokazivač na posredan način,
ali kako pristupiti tom pokazivač, ima da ga dereference.
Ili, kako bi pristupili ono što bi trebao biti ukazujući na, on ga dereferences.
Dakle, to je dereferencing null pokazivač i to segfaults.
Mogao sam ga ponovno tamo.
Ako smo razbiti u našem glavnom točkom i pokrenuti,
Prva linija koda je char * filename = "nonexistent.txt";
To bi trebalo dati prilično veliku savjet o tome zašto ovaj program ne uspije.
Tipkanje pored me dovodi do sljedećeg retka, gdje sam otvoriti ovu datoteku,
i onda sam odmah ući u našu liniju, gdje je nekada sam pogodio sljedeći, to će segfault.
Se bilo tko želi izbaciti razlog zašto bismo se segfaulting?
[Student] Datoteka ne postoji. >> Da.
To je trebao biti nagovještaj
da kad god otvaranja datoteku trebate provjeriti da datoteka zapravo postoji.
Dakle, ovdje, "nonexistent.txt";
Kada smo fopen filename za čitanje, onda ćemo morati reći
if (file == NULL) i reći printf ("Datoteka ne postoji!"
ili - još bolje - filename); povratak 1;
Dakle, sada smo provjeriti da li je NULL
prije nego što zapravo nastavlja i težak za čitanje iz te datoteke.
Možemo ga remake samo da vidim da se to radi.
Namjeravao sam uključuju novu liniju.
Tako sada nonexistent.txt ne postoji.
Uvijek treba provjeriti za ovu vrstu stvar.
Uvijek treba provjeriti da li fopen vraća NULL.
Uvijek treba provjeriti kako bi bili sigurni da malloc ne vrati NULL,
inače segfault.
>> Sada buggy4.c.
Trčanje. Pretpostavljam da je ovaj čeka ulaz ili eventualno beskonačne petlje.
Da, to je beskonačna petlje.
Dakle buggy4. Čini se kao da smo beskonačni loop.
Možemo razbiti na glavni, pokrenuti naš program.
U gdb, dok skraćenica koristite je nedvosmislen
ili posebne skraćenice koje oni pružaju za vas,
onda možete koristiti n koristiti sljedeći, umjesto da se tip iz sljedećoj skroz.
I sad da sam pogodio n jednom, ja mogu samo pritisnite Enter zadržati ide pored
umjesto da se pogodio n Enter, n Enter, n Enter.
Čini se kao da sam u nekoj vrsti za petlje da se postavljaju niz [i] na 0.
Čini se kao da sam nikada nije sam nego iz ove for petlje.
Ako sam ja ispisali, pa sam je 2, onda ću ići sljedeći.
Ja ću ispisati, ja je tri, onda ću ići sljedeći.
Ja ću ispisati i ja je tri. Dalje, ja ispisati, ja je 4.
Zapravo, print sizeof (niz), tako da veličina polja je 20.
No, to izgleda kao da je neki poseban gdb naredba za odlazak dok se nešto dogodi.
To je kao postavljanje stanje na vrijednosti varijable. Ali ne sjećam se što je to.
Dakle, ako smo zadržati ide -
Što su vam rekli? Što ste dovesti do?
[Student] Da li se prikazati i dodati - >> Da. Dakle prikazati ja mogu pomoći.
Ako mi samo mogu prikazati, ona će staviti ovdje ono što vrijednost i je
tako da ne moram to ispisati svaki put.
Ako smo samo zadržati ide dalje, vidimo 0, 1, 2, 3, 4, 5, 0, 1, 2, 3, 4, 5, 0, 1, 2, 3, 4, 5.
Nešto se događa užasno krivo, a ja se vratiti na 0.
Gledajući buggy4.c, vidimo sve što se događa je int niz [5];
za (i = 0; i <= sizeof (polje); i + +)
Niz [i] = 0;
Što ćemo vidjeti da je krivo ovdje?
Kao savjet, kad sam bio događaj gdb buggy4 - ajmo razbiti glavna, mali -
Ja nisam ispis sizeof (array) samo da se vidi što je uvjet gdje sam napokon trebala izbiti.
Gdje sam? Jesam li pokrenuti?
Nisam proglasiti još.
Dakle ispisati sizeof (array), a to je 20,
koja se očekuje od moje polje je veličine pet i to je od pet brojeva,
tako da cijela stvar bi trebala biti 5 * sizeof (int) bajtova, gdje sizeof (int) teži da bude 4.
Dakle, sizeof (array) je 20.
Što bi to moglo biti?
[Student] Podijeljen sizeof (int). >> Da, / sizeof (int).
To izgleda kao da je još uvijek problem ovdje. Mislim da je to samo treba biti <
jer to je prilično puno uvijek <i nikada <=.
Sada ćemo razmišljati o tome zašto je to zapravo bio slomljen.
Se bilo tko imati nagađanja zašto je ja vratiti na 0 kroz svaku iteraciju petlje?
Jedina stvar unutar ovog što se događa je da niz [i] se postavlja na 0..
Tako nekako, ova linija koda uzrokuje našu int ja biti postavljen na 0.
[Student] Može li to biti, jer to je najvažniji sjećanje na ovom dijelu ja
kad misli da je sljedeći element niza? >> [Bowden] Da.
Kad idemo van kraju našeg polja,
nekako taj prostor da smo prevladavajućeg je prevladavajućeg vrijednost i..
I tako, ako gledamo u buggy4, razbiti glavni, trčanje,
ajmo ispisati adresu ja.
To izgleda kao da je bffff124.
Sada ćemo ispisati adresu niz [0]. 110.
Što o [1]? 114.
[2], 118.
11c, 120. array [5] bfff124.
Dakle, niz [5] ima istu adresu kao što sam, što znači da je niz [5] ja.
Ako imaju istu adresu, oni su ista stvar.
Dakle, kada smo postavili niz [5] na 0, mi smo ja postavljanja na 0.
A ako mislite o tome u smislu stog,
int i je proglašen prvi, što znači da sam dobiva neke prostor na stog.
Tada niz [5] raspoređuje, pa onda 20 bytes se dodjeljuju na stog.
Dakle, ja dobiva dodijeljen prvi, onda ti 20 bajtova dobiti raspoređuje.
Dakle, ja se događa neposredno prije polju,
i zbog načina na koji, kao što sam rekao prošli tjedan, u kojoj je tehnički stog raste prema dolje,
kada indeks u polju, mi smo jamči da je 0. položaj u polju
uvijek događa prije na prvoj poziciji u polju.
To je vrsta kako sam ga izvukao prošli tjedan.
Primijetit ćete da na dnu imamo adresu 0 a na vrhu imamo adresu Max.
Stog uvijek raste prema dolje.
Ajmo reći da smo ja dodijeliti.
Mi izdvojiti cijeli ja, što znači da recimo samo da se ovdje cijeli ja dobiva dodijeljen.
Onda smo izdvojiti naš niz od 5 brojeva, što znači da se ispod koje,
budući da je stog raste prema dolje, te pet integeri se dodjeljuje.
Ali, jer kako polja rade, mi smo zajamčeno da prvu poziciju u polju
uvijek ima Adresa manje od drugog stvar u polju.
Dakle, niz položaj 0 uvijek mora dogoditi prvi u memoriju,
dok je niz poziciju 1 ima dogoditi nakon toga
i niz pozicija 2 mora se dogoditi nakon toga,
što znači da je 0 polje položaj će se dogoditi negdje ovdje dolje,
Niz poziciju jednog će se dogoditi iznad toga
jer se kreće prema gore znači veće adrese od maksimalno adresa je ovdje.
Dakle, niz [0] ovdje dolje, niz [1] ovdje, niz [2] ovdje, polje [3] ovdje.
Obavijest o tome kako smo prije izdvojila cijeli sam sve do ovdje,
kako idemo dalje i dalje u našem polju, mi smo sve bliže i bliže našem cijeli i..
To samo tako dogodi da array [5], koji je jedno mjesto izvan naše polje,
je točno gdje cijeli sam se dogodilo da se dodjeljuju.
Dakle, to je točka gdje smo se dogoditi da se udaranje prostora na stogu
koja je namijenjena za cijeli ja, a mi smo postavljanje da na 0.
>> To je kako da radi. Pitanja? Da.
[Student] Nikad pamet. Ok.
[Student] Kako ste izbjegli ove vrste pogreške?
Ovo vrsta pogrešaka? Nemojte koristiti C kao programskom jeziku.
Koristite jezik koji ima niz granice provjere.
Dokle god ste oprezni, trebate samo kako bi se izbjeglo ide prošlosti granica svoje polje.
[Student] Pa evo kad smo išli prošlosti granica svoje polje -
[Bowden] To je mjesto gdje se stvari početi idući krivu. >> [Student] Oh, u redu.
Dokle god vam ostati u sjećanju dodijeljenog za svoj niz, ti si u redu.
Ali C ne čini provjera. Ako mi je činiti niz [1000], on će rado samo mijenjati ono što se događa -
To ide na početku niza, onda to ide 1.000 pozicije nakon te ga postavlja na 0..
To ne činiti bilo provjere da oh, to zapravo ne imati 1000 stvari u njemu.
1000 je način izvan onoga što sam trebala mijenjati,
dok Java ili nešto što ćete dobiti niz od graničnih indeksa
ili indeks izvan granica iznimke.
To je razlog zašto puno višoj razini jezika imaju ove stvari
gdje ako idete izvan granica polja, možete uspjeti
tako da se ne mogu promijeniti stvari od ispod vas
i tada su se stvari ići puno gore nego samo dobivanje iznimku
govoreći da ode izvan kraja niza.
[Student] I tako bi mi samo promijenili <= samo <? >> [Bowden] Aha.
To bi trebao biti <sizeof (array) / sizeof (int);
jer sizeof (array) je 20, ali mi samo želimo pet. >> [Student] Točno.
Više pitanja? Ok.
>> [Student] imam pitanje. >> Da.
[Student] Što je stvarna varijabla?
[Bowden] Kao što je niz?
Array sama po sebi je simbol.
To je samo adresa početka 20 bajtova da smo referenciranje.
Možete misliti o njemu kao pokazivač, ali to je konstantna pokazivač.
Čim se stvari sastavio, varijabla polje više ne postoji.
[Student] Pa kako to pronaći veličinu niza?
Veličina polja odnosi se na veličinu tog bloka koji se odnosi na simbol.
Kad sam napraviti nešto poput printf ("% p \ n", niz);
ajmo ga pokrenuti.
Što sam samo krivo?
Array 'polje' proglašen ovdje.
Oh, ovdje.
Jeka je pametan, a to se događa da se primjetiti da sam proglašen niz kao pet elemenata
ali ja sam indeksiranje u poziciju 1000.
To se može učiniti, jer to su samo konstante.
To samo može ići tako daleko u primjećujući da idem van granica niza.
Ali primijetite prije, kada smo imali ja biti kriv,
to nikako ne može utvrditi koliko je vrijednosti i može se na,
tako da se ne može utvrditi da sam bio idući iza kraja niza.
To je samo jeka bude pametan.
>> Ali sada bi buggy4. Pa što drugo radim krivo?
Implicitno proglašenja knjižnica funkcija 'printf'.
Idem želite # include .
Ok. Sada radi buggy4.
Ispis vrijednost polja kao što sam učinio ovdje, to tisak kao pokazivač
ispisuje nešto što izgleda ovako - bfb8805c - što je neke adresa
da je u stog-ish regiji.
Array sama je kao pokazivač, ali to nije stvarni pokazivač,
od obične pokazivač možemo promijeniti.
Array je samo neka konstanta. 20 blokova memorije početi na adresi 0xbfb8805c.
Dakle bfb8805c kroz ovu adresu +20--ili valjda -20 -
je sve memorije dodijeljenog za ovaj niz.
Array, varijabla sama nije pohranjena bilo gdje.
Kada ste sastavljanje, prevodilac - ruka val na njega -
ali prevodilac će samo koristiti gdje zna polje biti.
To zna gdje da niz počinje,
i tako se uvijek može učiniti samo stvari u smislu offseta od tog početka.
To ne treba varijablu sama za zastupanje niz.
Ali kad sam učiniti nešto poput int * p = array; sada je p pokazivač koji pokazuje na tom polju,
a sada p zapravo ne postoji na stog.
Ja sam slobodan promijeniti str. Ja mogu učiniti p = malloc.
Dakle, to je izvorno je ukazao na niz, a sada to ukazuje na nekom prostoru na hrpi.
Ja ne mogu napraviti array = malloc.
Ako zveka je pametan, on će vikati na mene pravo isključiti šišmiš.
Zapravo, prilično sam siguran gcc će to učiniti previše.
Dakle, niz tipa 'int [5]' nije prenosiv.
Vi ne možete dodijeliti nešto na niz tipa
jer niz je samo konstanta.
To je simbol koji reference te 20 bajtova. Ja to ne mogu promijeniti.
>> [Student] A gdje je veličina polja pohranjena?
[Bowden] To nije pohranjena bilo gdje. To je kada je sastavljanje.
Dakle, gdje je veličina polja pohranjena?
Možete koristiti samo sizeof (array) unutar funkcije koje polje je sama proglasila.
Dakle, ako sam napraviti neke funkcije, Foo, i ja (int niz [])
printf ("% d \ n", sizeof (polje));
i onda ovdje dolje zovem foo (Niz);
unutar ove funkcije - ajmo ga pokrenuti.
To je jeka bude pametan opet.
To mi govori da je sizeof na polja funkcije parametra
će se vratiti veličinu 'int *'.
To će biti pogreška ako to nije ono što sam htjela da se dogodi.
Ajmo zapravo isključiti Werror.
Upozorenje. Upozorenja su u redu.
To će ipak sastaviti dok ima upozorenje.
. / A.out će ispisati 4.
Upozorenje koje je generiran je jasan pokazatelj onoga što je pošlo po zlu.
Ovo int polje samo ide za ispis sizeof (int *).
Čak i ako sam stavio niz [5] ovdje, to je još uvijek samo ide za ispis sizeof (int *).
Dakle, čim to prođe u funkciji, razlika između polja i pokazivače
je nepostojeći.
To se događa da se niz koji je proglašen na stog,
ali čim mi prođe tu vrijednost, da 0xbf bla, bla, bla, u ovoj funkciji,
onda je to pokazivač pokazuje na tom polju na stog.
Dakle, to znači da sizeof se primjenjuje samo u funkciji da polje je proglašeno,
što znači da kada ste sastavljanju ovu funkciju,
kada zveka prolazi kroz ove funkcije, ona vidi polje je int niz veličine pet.
Pa onda vidi sizeof (niz). Pa, to je 20.
To je zapravo kako sizeof osnovi radi za gotovo svim slučajevima.
Sizeof nije funkcija, to je operater.
Vi ne zvati sizeof funkciju.
Sizeof (int), prevodilac će samo prevesti do četiri.
Kužite? Ok.
>> [Student] Pa što je razlika između sizeof (array) u glavni i foo?
To je zato što smo govoreći sizeof (array), koji je tipa int *,
dok je niz ovdje nije tipa int *, to je int polje.
>> [Student] Dakle, ako ste imali parametar u polju [] umjesto int * niz,
bi to značilo da se još uvijek mogu promijeniti niz, jer sada je pokazivač?
[Bowden] Kao ovo? >> [Student] Aha. Mogu li promijeniti niz u funkciji sada?
[Bowden] Ti bi mogao promijeniti niz u oba slučaja.
U oba slučaja ste slobodni reći array [4] = 0.
[Student] Ali možete napraviti polje točku na nešto drugo?
[Bowden] Aha. Da. U svakom slučaju - >> [student] Aha.
[Bowden] Razlika između niz [] i int * niz, nema.
Također možete dobiti neki višedimenzionalni niz u ovdje
za neke zgodan sintakse, ali to je još uvijek samo pokazivač.
To znači da sam slobodan činiti niz = malloc (sizeof (int)), a sada istaknuti negdje drugdje.
No, baš kao i kako se to radi zauvijek i uvijek,
mijenja ovaj niz čineći ga ukazati na nešto drugo
ne mijenja ovu lepezu ovdje dolje, jer to je kopija argumenta,
to nije pokazivač na taj argument.
A zapravo, baš kao što više naznaka da je to točno isti -
smo već vidjeli što otisaka ispis Array -
što ako smo ispisali adresu niz ili adresu na adresu niz
na bilo koji od tih?
Ajmo ignorirati ovaj jedan.
Ok. To je u redu. Sada je trčanje. / A.out.
Tiskanje polje, a zatim ispisati adresu niz, su ista stvar.
Array jednostavno ne postoji.
To zna kada ste tiskanje niz, ti si ispis simbol koji se odnosi na tih 20 bajtova.
Ispis adresu polju, dobro, polje ne postoji.
To ne imati adresu, tako da samo ispisuje adresu onih 20 bajtova.
Čim sastaviti dolje, kao u vašem sastavio buggy4. / A.out,
Niz je nepostojeći.
Pokazivači postoji. Nizovi ne.
Blokovi memorije predstavljaju niz još uvijek postoje,
ali varijabla polje i varijable tog tipa ne postoje.
Oni su kao glavne razlike između polja i pokazivače
se čim bi funkcijske pozive, ne postoji razlika.
No, unutar funkcije koje polje sama proglasila, sizeof radi drugačije
budući da ispisujete na veličinu blokova umjesto veličini vrsti,
i ne možete ga promijeniti, jer to je simbol.
Ispis stvar i adresu stvar ispisuje istu stvar.
I to je uglavnom to.
[Student] Može li se reći da jedan više vremena?
Možda sam nešto propustio.
Tiskanje polje i adresa niz ispisuje istu stvar,
a ako ispisujete pokazivač u odnosu na adresu pokazivača,
jedna stvar ispisuje adresu što ste pokazujući na,
druga ispisuje adresu pokazivača na stog.
Možete promijeniti pokazivač, vi ne možete promijeniti niz simbola.
A sizeof Pokazivač će se ispisati veličinu tog tipa pokazivača.
Dakle, int * p sizeof (p) će ispisati 4,
ali int niz [5] ispis sizeof (array) ide za ispis 20.
[Student] Pa int niz [5] će ispisati 20? >> Da.
To je razlog zašto unutar buggy4 kada je nekad bila sizeof (array)
to je radio i <20, što nije ono što smo htjeli.
Želimo I <5. >> [Student] Ok.
[Bowden] I onda čim počnete prolazi u funkcijama,
ako nismo int * p = array;
unutar ove funkcije, mi u osnovi može koristiti p i lepezu na isti način,
osim za sizeof problema i mijenja problema.
Ali p [0] = 1; je isti kao i govoreći niz [0] = 1;
I čim smo rekli foo (Niz), ili Foo (p);
unutar foo funkcije, to je isti poziv dvaput.
Nema razlike između tih dvaju poziva.
>> Svatko dobro na to? Ok.
Imamo 10 minuta.
>> Mi ćemo pokušati da se kroz ovaj program Hacker Typer,
ova web stranica, koji je izašao prošle godine ili tako nešto.
To je samo trebao biti poput upišete slučajno i to ispisuje -
Što god datoteka se dogodi da su učitani je ono što izgleda kao da ste tipkati.
To izgleda kao neka vrsta operativnog sustava koda.
To je ono što želimo provesti.
Trebali bi imati binarni executable zove hacker_typer
koji uzima u jedan argument, datoteke "hakerske tipa."
Trčanje izvršnu treba očistiti ekran
a zatim ispisati jedan lik iz položen-u datoteci svaki put korisnik pritisne tipku.
Dakle, bez obzira na tipku pritiskom, to bi trebalo baciti i umjesto toga ispisati lik iz spisa
da je argument.
Ja ću prilično puno vam reći što su stvari koje ćete trebati znati jesu.
No, želimo provjeriti termios knjižnicu.
Ja nikad nisu koristili ovu knjižnicu u mom cijelom životu, tako da ima vrlo minimalne svrhe.
No, ovo će biti knjižnica možemo koristiti za baciti karakter ćete pogoditi
kada kucate u standardu u.
Dakle hacker_typer.c, a mi si idući u ištanje to # include .
Gledajući na čovjeka stranici za termios - Ja sam guessing da je terminal OS ili nešto -
Ne znam kako da ga pročitate.
Gledajući na to, kaže da su ove dvije datoteke, tako da ćemo to učiniti.
>> Prva stvar prvo, želimo da se u jedan argument, koji je datoteka bismo trebali otvoriti.
Dakle, ono što želim učiniti? Kako mogu provjeriti da vidi imam jednu argument?
[Student] Ako argc ga jednako. >> [Bowden] Aha.
Dakle, ako (argc = 2!) Printf ("Korištenje:% s [file otvoriti]").
Pa sad, ako sam pokrenuti to bez pružanja drugi argument - Oh, trebam novu liniju -
vidjet ćete da kaže korištenja:. / hacker_typer,
i onda drugi argument bi trebao biti file Želim otvoriti.
Sada što da radim?
Želim pročitati iz ove datoteke. Kako sam pročitao iz datoteke?
[Student] Ti ga otvorili prvi. >> Da.
Dakle fopen. Što fopen izgledati?
[Student] slici. >> [Bowden] Naziv će biti argv [1].
[Student] A onda ono što želite učiniti s njom, pa - >> [Bowden] Aha.
Dakle, ako vam se ne sjeća, samo mogao učiniti čovjek fopen,
gdje će to biti const char * put gdje put je filename,
const char * mod.
Ako vam se dogoditi da se ne sjećam što je način, onda možete tražiti način.
Unutar man stranica, udarac lik je ono što se može koristiti za traženje stvari.
Tako sam upisati / mod za traženje modu.
n i N su ono što možete koristiti za kretanje kroz pretraživanja utakmice.
Evo što kaže bodove argumenata načina na žici
počevši s jednim od sljedećih sekvenci.
Dakle, r, Otvoreno tekstualna datoteka za čitanje. To je ono što želimo učiniti.
Za čitanje, a ja želim da pohraniti.
Stvar će biti SLIKA *. Sada ono što želim učiniti?
Daj mi drugi.
Ok. Sada ono što želim učiniti?
[Student] Provjerite ako je NULL. >> [Bowden] Aha.
Svaki put kada otvorite datoteku, pobrinite se da ste uspješno moći otvoriti.
>> Sada želim to učiniti termios stvari gdje želim da prvo pročitate moje trenutne postavke
i spasiti one u nešto, onda želim promijeniti svoje postavke
baciti bilo koji znak da sam upisati,
i onda želim ažurirati te postavke.
I onda na kraju programa, želim se vratiti na moje izvorne postavke.
Dakle struct će biti tipa termios, a ja ću htjeti dvije od tih.
Prvi će biti moji current_settings,
i onda oni će biti moji hacker_settings.
Prvo, ja ću žele spasiti svoje trenutne postavke,
onda ću htjeti ažurirati hacker_settings,
a zatim način na kraju mog programa, želim se vratiti na trenutnim postavkama.
Dakle štedi trenutne postavke, način na koji funkcionira, mi čovjek termios.
Mi vidimo da imamo ovu int tcsetattr, int tcgetattr.
Ja proći u termios struct po svojoj pokazivača.
Put će to izgledati je - I've već zaboravili što je funkcija zvao.
Kopirajte i zalijepite.
Dakle tcgetattr, onda želim da prođe u struct da sam spremanja informacija u,
koji će biti current_settings,
i prvi argument je datoteka deskriptor za stvar koju želim spasiti atribute.
Što file deskriptor je kao i svaki put kada otvorite datoteku, ona dobiva file deskriptor.
Kad sam fopen argv [1], on dobiva datotečni deskriptor koji ste referenciranje
kada želite čitati ni pisati na njega.
To nije datoteka deskriptor želim koristiti ovdje.
Postoje tri datoteke deskriptori imate po defaultu,
koji su standardni u, standardni van, a standardna pogreška.
Po defaultu, mislim da je to standard u je 0, standardni izlaz je 1, a standardna pogreška je dva.
Dakle, ono što želim promijeniti postavke?
Želim promijeniti postavke svaki put kad sam pogodio karakter,
Želim ga baciti taj lik daleko, umjesto da ga ispisuje na zaslonu.
Što potok - standard u, standardni izlaz, ili standardne pogreške -
reagira na stvari kad sam upisati na tipkovnici? >> [Student] Standardna u. >> Da.
Tako sam može učiniti 0 ili ja mogu učiniti stdin.
Ja sam uzimajući current_settings o standardu u.
>> Sada želim ažurirati te postavke,
pa prvi ću kopirati u hacker_settings što moji current_settings su.
A kako tvorevina, rad je to samo će kopirati.
Ovo kopira sva polja, kao što se i očekuje.
>> Sada želim ažurirati neke od polja.
Gledajući termios, te će morati pročitati kroz mnogo toga
samo da vidim ono što želite tražiti,
ali su zastave idete da želite tražiti su jeka,
tako Echo Echo ulaznih znakova.
Prvo želim postaviti - I've već zaboravili što su polja.
To je ono što struct izgleda.
Dakle, načini unosa Mislim želimo promijeniti.
Mi ćemo gledati na rješenje kako bi bili sigurni da je ono što želimo promijeniti.
Želimo promijeniti lflag kako bi se spriječilo trebaju gledati kroz sve to.
Želimo promijeniti lokalne načina.
Ti bi da pročitate kroz cijelu ovu stvar za razumjeti gdje sve pripada
da želimo promijeniti.
Ali to je unutar lokalnih načina gdje idemo da žele da se to promijeni.
Dakle hacker_settings.cc_lmode je ono što se zove.
c_lflag.
To je mjesto gdje smo dobili u bitovni operatori.
Mi smo vrsta izvan vremena, ali mi ćemo proći kroz to vrlo brzo.
To je mjesto gdje smo dobili u bitovni operatori,
gdje mislim da sam rekao jedno vrijeme davno da kad počnete bave zastavama,
ti si idući u biti koristeći bitovni operateru puno.
Svaki malo u zastavom odgovara nekom vrstom ponašanja.
Dakle, ovo zastava ima hrpa različitih stvari, gdje svi od njih znači nešto drugo.
No, ono što želim učiniti je samo isključiti malo koja odgovara ECHO.
Tako da se to off radim & = ¬ ECHO.
Zapravo, mislim da je to kao tECHO ili nešto. Samo ću provjeriti opet.
Mogu ga termios. To je samo ECHO.
ECHO će biti jedan malo.
¬ ECHO će značiti sve bitova su postavljena na 1, što znači da su sve zastave postavljen na true
osim za ECHO malo.
Do završetka moje lokalne zastave s tim, to znači sve zastave koje su trenutno postavljene na true
i dalje će biti postavljen na true.
Ako je moja ECHO zastava postavljena na true, onda je to nužno postavljena na False na ECHO zastavom.
Dakle, ova linija koda samo gasi ECHO zastavu.
Druga linija koda, samo ću kopirati ih u interesu vremena, a zatim ih objasniti.
U otopini, rekao 0.
To je vjerojatno bolje da eksplicitno reći stdin.
>> Primijetit ćete da sam i radim ECHO | ICANON ovdje.
ICANON se odnosi na nešto odvojeno, što znači kanonski način.
Što kanonski način znači da je obično kada pišete iz naredbenog retka,
standard u ne obrađuje ništa dok ne pogoditi newline.
Dakle, kada ne GetString, upišete hrpu stvari, onda pogodio novi red.
To je kad je poslan na standardu u.
To je zadana.
Kad sam isključiti kanonski način, sada svaki pojedinačni znak da pritisnete
je ono što dobiva obrađuju, što je obično vrsta loše jer je spor za obradu tih stvari,
što je razlog zašto je dobro da ga tampon u cijelom linije.
Ali ja želim svaki lik koji se obrađuju
jer ne želim da čekati za mene pogoditi newline
prije obrađuje sve znakove sam tipkati.
To isključuje kanonski način.
Ova stvar samo znači kada se zapravo obrađuje likove.
To znači da ih obraditi odmah, čim sam ih tipkati, obraditi ih.
A to je funkcija koja se ažurira svoje postavke za standardne u,
i TCSA znači to učiniti upravo sada.
Ostale opcije su čekati dok sve što je trenutno na potoku obrađuju.
To ne stvarno tvar.
Samo sada promijeniti moje postavke da se ono što je trenutno u hacker_typer_settings.
Mislim da su to nazvali hacker_settings, pa ajmo to promijeniti.
Promjena sve do hacker_settings.
>> Sada je na kraju našeg programa ćemo se želite vratiti
na ono što je trenutno unutar normal_settings,
koji će samo izgledati i normal_settings.
Obavijest nisam promijenio bilo koje od mojih normal_settings od prvotno uzimajući ga.
Zatim ih vratiti, ja ih proći natrag na kraju.
Ovo je ažuriranje. Ok.
>> Sada unutar ovog ću samo objasniti kod u interesu vrijeme.
To nije toliko koda.
Vidimo čitamo lik iz spisa. Zvali smo ga f.
Sada možete Čovjek fgetc, ali kako fgetc ide na posao
se samo da će se vratiti karakter koji ste upravo pročitali ili EOF,
koji odgovara kraju datoteke ili neke pogreške događa.
Mi smo petlje, nastavljajući čitati jedan znak iz datoteke,
dok smo ponestane znakova za čitanje.
I dok radimo da, čekamo na jednom lik iz standarda i.
Svaki put kada upišete nešto u zapovjednoj liniji,
da je čitanje u lik iz standardu u.
Zatim Putchar samo će staviti char čitamo ovdje iz datoteke na standardni izlaz.
Možete čovjek Putchar, ali to je samo stavljanje na standardu van, to znači tiskanje taj lik.
Također se može učiniti samo printf ("% c", c); istu ideju.
To će učiniti većinu našeg rada.
>> Zadnja stvar koju idete da želite učiniti je samo fclose našu datoteku.
Ako ne fclose, to je gubljenje memorije.
Želimo fclose datoteku smo prvotno otvorena, i ja mislim da je to to.
Ako ćemo napraviti da, ja već imam problema.
Idemo vidjeti.
Što je to žaliti?
Očekivani 'int', ali argument je tipa 'struct _IO_FILE *'.
Mi ćemo vidjeti ako to radi.
Samo dozvoljeno C99. Augh. Ok, napraviti hacker_typer.
Sada smo dobili više korisnih opise.
Dakle, koristite neprijavljenog identifikator 'normal_settings'.
Nisam ga zovu normal_settings. Zvao sam ga current_settings.
Tako ćemo promijeniti sve to.
Sada prolazi argument.
Ja ću napraviti ovaj 0 za sada.
Ok. . / Hacker_typer cp.c.
Ja također nije jasan zaslon na početku.
No, možete se osvrnuti na zadnji problema setu vidjeti kako ste izbrisali zaslon.
To je samo tiskanje neke znakove
dok se to radi ono što želim učiniti.
Ok.
I razmišljam o tome zašto se to moralo biti 0, umjesto stdin,
koji bi trebao imati # define 0,
to se žali da je -
Prije kad sam rekao da postoji datoteka deskriptori, ali onda također imaju svoje FILE *,
file deskriptor je samo jedan broj,
dok SLIKA * ima hrpu stvari povezane s njom.
Razlog moramo reći 0 umjesto stdin
je da je stdin SLIKA * što ukazuje na stvari koje se pozivom file deskriptor 0.
Dakle, čak i ovdje kad sam to fopen (argv [1], ja sam uzimajući FILE * natrag.
No, negdje u tom FILE * je stvar odgovara file deskriptora za tu datoteku.
Ako pogledate na čovjeka stranici za otvaranje, tako da mislim da ćete morati učiniti čovjek tri otvorena - nope -
Čovjek dva otvorena - Da.
Ako pogledate na stranici za opena, otvoren je kao niže razine fopen,
a to je povratak u stvarni file deskriptor.
fopen ne hrpa stvari na vrhu opena,
koji umjesto povratka samo da file deskriptor vraća cijelu datoteku * pokazivač
unutar koje je naša mala file deskriptor.
Dakle standard u odnosi na stvar FILE *,
a 0 se odnosi na samo na standard file deskriptor u sebi.
>> Pitanja?
[Smijeh] puhao kroz to.
U redu. Mi smo učinili. [Smijeh]
>> [CS50.TV]