[Powered by Google Translate] [Oddelek 5 - Več Udobna]
[Rob Bowden - Harvard University]
[To je CS50. - CS50.TV]
>> Kot sem že povedal v e-pošti, obstaja veliko stvari, ki jih lahko uporabite
razen naprave za dejansko storiti težavnih sprejemnikov.
Priporočamo, da to storite v napravi samo zato, ker potem bomo lahko lažje pomagal
in vemo, kako se vse dogaja na delo.
Ampak kot en primer, kjer lahko narediš stvari, če, recimo, nimate dostopa
na napravo ali pa bi radi delali v kleti Science Center -
ki dejansko imajo aparat preveč -
če želite, da dela kjer koli.
Eden od primerov so se ga videli / slišali SSH?
SSH je v bistvu tako, kot povezavo z nečim.
Pravzaprav, zdaj sem SSHed v napravo.
Nikoli ne delajo neposredno v napravi.
Tukaj je aparat, in če pogledate tukaj vidite ta naslov IP.
Ne delam v aparatu samem;
Vedno sem prišel do iTerm2 okno / okna terminala.
Lahko SSH ta IP naslov, ssh jharvard@192.168.129.128.
Spomnim se, da je število zelo enostavno, ker je tako lep vzorec.
Vendar pa bo, da me prosi za geslo, in zdaj sem v napravi.
V bistvu, v tem trenutku, če ste odprli terminal v notranjosti aparata samega,
ta vmesnik, vendar bi jo uporabili, je popolnoma enak
kot vmesnik sem z tukaj, zdaj pa si ti SSHed.
Nimaš SSH na napravi.
En primer drugo mesto si lahko SSH, je Prepričan sem, da imate privzeto -
Oh. Večji.
Vsi vi bi morali z računov privzete FAS na strežnikih FAS.
Za mene, jaz bi SSH za rbowden@nice.fas.harvard.edu.
To se dogaja, da vas prosim, da je prvič, in si rekla da.
Moje geslo je le, da bo moj FAS geslo.
In sedaj, sem SSHed z lepimi strežnikov, in jaz lahko naredim kar želim tukaj.
Veliko razredov se lahko sprejme kot 124, se dogaja, da imajo lahko naložite stvari tukaj
treba dejansko predložiti tvoj problem sklopov.
Ampak pravijo, da nimajo dostopa do vašega aparata.
Potem lahko narediš stvari, kot tukaj bo rekel -
To je samo naš del vprašanj.
Vprašal vas bo, da to stori v napravi.
Namesto tega bom samo to na strežniku.
Grem, da razširite.
Problem se bo, da ste navajeni na uporabo nekaj podobnega gedit
ali karkoli notranjost stroja.
Saj ne bo imel, da na FAS strežniku.
To je vse samo, da bo tako tekstovni vmesnik.
Torej si lahko bodisi eno, naučiti urejevalnik besedila, da to so.
Imajo Nano.
Nano je ponavadi zelo enostaven za uporabo.
Lahko uporabite svoje puščice in vnesite kot običajno.
Torej, to ni težko.
Če želite res fancy znate uporabljati Emacs,
, ki najbrž ne bi smela začeti, ker ne vedo, kako blizu Emacsa.
Nadzor X, nadzor C? Ja.
Lahko pa uporabite vim, ki je tisto, kar sem uporabo.
In tako so se vaše možnosti.
Če ne želiš, da si lahko tudi, če pogledaš na manual.cs50.net, -
Oh.
Na računalniku, lahko uporabljate SSH PuTTY,
kar boste morali ločeno prenesete.
Na Mac, si lahko samo z uporabo privzetega terminala ali si lahko prenesete iTerm2,
ki je kot lep, fancy terminala.
Če greste na manual.cs50.net boste videli povezavo do Beležnica + +,
, ki je tisto, kar lahko uporabite v računalniku.
To vam omogoča, SFTP iz Notepad + +, ki je v bistvu SSH.
Kaj bo to kaj morate storiti, je urejanje datotek na lokalni ravni,
in potem, ko jih želite shraniti, bo shranite na nice.fas,
kjer se lahko nato zagnati.
In enako na Mac se bo TextWrangler.
Tako vam omogoča, da storijo enako stvar.
To vam omogoča urejanje datotek na lokalni ravni in jih shranite v nice.fas,
kjer se lahko nato zagnati.
Torej, če ste kdaj zaljubljen, ne da bi napravo, imate te možnosti
da še vedno vaš problem sklopov.
En problem se bo, da ne boš imel CS50 knjižnico
ker nice.fas ne privzeto imeti.
Lahko prenesete CS50 knjižnice -
Mislim, da ne rabim, da na tej točki.
Lahko prenesete CS50 knjižnico in jo kopirajte v leto nice.fas,
ali Mislim, da na tej točki ne uporabljajo več vseeno.
Ali pa, če mi lahko zaenkrat ga nadomestiti z
izvedb funkcij v knjižnici CS50 vseeno.
Tako, da ne bi smelo biti, da je veliko omejitev.
In to je to.
>> Grem nazaj na aparat zdaj, bomo naredili vse, kar je v napravi.
Če pogledamo na našem oddelku vprašanj, na začetku, kot sem že povedal v e-pošti,
moramo govoriti o eni kratki Moral bi gledati.
Imamo preusmerjanje in cevi in ​​teh treh vprašanj.
>> Na kateri tok ne deluje kot printf napisal privzeto?
Torej tok. Kaj je tok?
Tok je v bistvu, kot da je samo nekaj -
To sploh ni vir 1s in 0s.
Potok se prosi za tukaj je standard ven.
In tako je iz standarda tok, ko pišete z njim,
se pojavi na zaslonu.
Enostavno, tako da jim tok, to pomeni, da le napišeš 1s in 0s z njim,
in drugi konec standardni izhod le bere iz tega toka.
To je samo niz 1s in 0s.
Lahko pišete na vodotokih, ali si lahko preberete iz tokov
odvisno od tega, kaj dejansko je tok.
Drugi dve privzete tokovi so standard v in standardno napako.
Standard je, ko vam GetString, da te čaka, da stvari vhoda.
Torej vas čaka, to je pravzaprav čaka na standard v,
kar je res tisto, kar dobiš, ko vnesete na tipkovnici.
Tipkate v standardu palcev
Standardna napaka je v bistvu enaka standardni izhod,
vendar je specializirana v tem, da pri tiskanju v standardne napake,
ti naj bi samo tiskanje sporočil o napakah v tem
tako da lahko razlikuje med rednimi sporočila izpisujejo na zaslonu
v primerjavi sporočil o napakah glede na to, ali so šli ven standardno ali standardne napake.
Datoteke preveč.
Standardna ven, standard, standardna napaka in so le posebni tokovi,
ampak res vse datoteke, ko odprete datoteko, postane tok bajtov
kjer si lahko prebral iz tega toka.
Ti, za večino del, lahko samo pomislite datoteke kot tok bajtov.
Torej, kaj tokovi pa so napisali, da je privzeto? Standardna ven.
>> Kakšna je razlika med> in >>?
Ali je kdo gledal video vnaprej? Ok.
> Se bo, kako preusmeriti v datoteke,
in >> se tudi dogaja, da preusmerijo proizvodnjo v datoteke,
vendar je namesto tega bo priložiti k spisu.
Na primer, recimo, da sem se zgodi, da imajo narek tukaj,
in edina stvar znotraj narek je mačka, mačka, pes, ribe, pes.
En ukaz, da imate v ukazni vrstici je mačka,
, ki je šele pred tiskanjem, kar je v datoteki.
Torej, ko sem rekel, mačka narek, da se bo tiskanje mačko, mačka, pes, ribe, psa. To je vse kar počne mačka.
To pomeni, da se natisne v skladu s standardom iz mačko, mačka, pes, ribe, pes.
Če bi namesto tega želite preusmeriti, da datoteko, lahko uporabite> in jih preusmerili na kateri koli datoteke.
Poklical bom datoteko datoteko.
Torej, zdaj, če I ls, bom videl, da imam novo datoteko z imenom datoteke.
In če sem jo odprl, da se dogaja, da imajo kaj mačka dal v ukazni vrstici.
Torej, zdaj, če sem to storil še enkrat, nato pa se dogaja, da preusmerite izhod v datoteko,
in jaz bom imel točno isto stvar.
Torej, tehnično, popolnoma razveljavljena, kar smo imeli.
In bomo videli, če spremenim narek, sem peljal psa.
Zdaj, če mačka narek v datoteko znova, da bomo imeli novo različico s psom odstranijo.
Torej je to popolnoma prekrije.
Namesto tega, če bomo uporabili >>, da se bo dodati datoteko.
Zdaj, odpiranje datotek, vidimo, imamo ravno isto stvar dvakrat natisnjen
ker je bila tam nekoč, potem priložen original.
Torej, to je tisto,> in >> storiti.
Ali naslednjič vprašal - ne sprašujejo o tem.
>> Drugi pa, da smo se <, ki bi, če> preusmeri standardni izhod,
<Se bo preusmeriti standarda noter
Poglejmo, če bomo imeli za zgled.
Znam napisati en pravi hitro.
Vzemimo poljubne datoteke, hello.c.
Razmeroma preprosta datoteka.
Jaz sem samo dobili niz in nato tiskanje "Hello", ne glede na niz sem začel bilo.
Torej, da zdravo in potem. / Zdravo.
Zdaj pa me je spodbudilo, da vnesete nekaj,
kar pomeni, da čaka na stvari, ki jih je treba vnesti v standardu palcev
Torej, kar hočem vnesti v standardu noter bomo samo rekli Zdravo, Rob!
Potem je tiskanje s standardom iz Zdravo, Rob!
Če naredim. / Zdravo in preusmerite,
Za zdaj lahko samo preusmeriti iz datoteke.
Torej, če sem dal v nekaj dokumentacije, txt, in sem dal Rob,
če sem teči zdravo in preusmerite v datoteko txt. / halo, to bo rekel Zdravo, Rob! takoj.
Ko se je prvič pride do GetString in čaka na standardu v,
standard ni več čakanja na tipkovnici za podatke, da se je začel.
Namesto tega smo preusmerili standard za branje iz datoteke txt.
In tako se dogaja, da bere iz datoteke txt, ki je ravno črto Rob,
in potem se dogaja, da tiskanje Hello, Rob!
In če bi hotel, bi tudi jaz naredil. / Zdravo <txt
in potem standard, da je tiskanje, ki je Zdravo, Rob!,
Ne morem preusmeriti, da v svojo datoteko.
Poklical bom datoteko zdravo - ne, ne bom, ker je to izvedljivo - txt2.
Zdaj txt2 se dogaja, da imajo izhod. / Zdravo <txt, ki se bo Pozdravljeni, Rob!
>> Vprašanja?
>> Ok. Torej imamo tukaj cevovoda.
Cevi so zadnja enota preusmeritev.
>> Oh. Mislim, da ena enota preusmeritve je, če namesto> narediš 2>,
, ki je preusmeritev standardno napako.
Torej, če je šlo nekaj za standardno napako, da ne bi dobili začnejo txt2.
Toda opazil, če sem naredil 2>, nato pa je še vedno tiskanje Zdravo, Rob! v ukazni vrstici
ker sem samo preusmerjanje standardna napaka, jaz ne preusmerja standarda ven.
Standardna napaka in standard iz drugačne.
Če bi želeli, da bi dejansko napisali, da standardna napaka,
potem bi lahko spremenili, da je to ovrednotenj v stderr.
Torej printf, ki ga privzeto tiska na standardni izhod.
Če želim tiskati na standardne napake ročno, nato pa sem moral uporabiti ovrednotenj
in določite, kaj želite tiskati.
Če namesto tega sem ovrednotenj stdout, nato pa, da je v bistvu enaka printf.
Ampak ovrednotenj za standardno napako.
Torej, zdaj, če sem to preusmeriti v txt2, Zdravo, Rob! se bo še natisnjena v ukazni vrstici
saj je bilo pridobivanje natisnjena na standardne napake in sem samo preusmerjanje standarda ven.
Če sem zdaj preusmeriti standardne napake, zdaj ga ni dobil natisniti in txt2 se bo Pozdravljeni, Rob!
Torej, zdaj, lahko natisnete vaše dejanske napake, s standardno napako
in tiskanje redne sporočila out standard.
In tako, ko zaženete program, ga lahko zaženete kot. / Pozdravi to vrsto z 2>
tako da vaš program se bo normalno teči,
vendar pa lahko sporočila o napaki, ki ga dobiš preverite kasneje v svojem dnevniku napak,
Tako napak, nato pa poiščite in pozneje svoje napake, datoteka ne bo imela nobenih napak, ki so se zgodili.
>> Vprašanja?
>> Zadnji je cev, ki jo lahko mislili, pri čemer standard ven iz enega ukaza
in kar je standard v naslednjem ukazu.
Primer za to je odmev je stvar ukazni vrstici
da se bo kar odmeva, kar sem dal v svoje trditve. Ne bom dal ponudbe.
Echo bla, bla, bla je le, da bo tiskanje bla, bla, bla.
Prej, ko sem rekel, da moram dati Rob v txt datoteko
saj lahko le preusmeriti txt datoteke, namesto, / če bom echo Rob
, nato pa je v cevi. / zdravo, da bo tudi storila isto vrsto stvari.
To traja proizvodnje tega ukaza echo, Rob,
in kot prispevku. / zdravo.
Lahko pomislite, da je prva preusmeritev odmeva Rob v datoteko
in nato vneseni v. / halo tega spisa je bil, da samo izhodne.
Vendar pa meni, začasne datoteke iz slike.
>> Vprašanja o tem?
>> Naslednje vprašanje bo vključevalo to.
Kaj plinovoda lahko uporabite, da bi našli številne edinstvene imen v datoteko, imenovano names.txt?
Ukazi bomo želeli uporabiti tu so edinstveni, tako uniq, nato wc.
To lahko storite človek unikatnega dejansko pogledati, kaj to naredi,
in to je le, da bo filter sosednje ujemanje črte od vhoda.
In človek, wc bo tiskanje novo vrstico, Word in bajtov za vsako datoteko.
In zadnja bomo želeli uporabiti, je vrsta,
ki se bo nekako linije txt datoteko.
Če naredim nekaj datoteko txt, names.txt, in to je Rob, Tommy, Joseph, Tommy, Joseph, RJ, Rob,
kar želim tukaj storiti, je najti številne edinstvene imen v tej zadevi.
Torej, kaj bi moral biti odgovor? >> [Študent] 4. >> Ja.
To bi moral biti 4 leta Rob, Tommy, Jožef, RJ so enolično Imena v tej zadevi.
Prvi korak, če sem naredil število besed na names.txt,
To je pravzaprav vse, kar mi povedal.
To je pravzaprav tisk - Poglejmo, človek wc - novih vrstic, besed in bajtov.
Če sem samo skrbi proge, nato pa sem naredil wc-l names.txt.
Torej, to je 1. korak.
Ampak jaz ne želim wc-l names.txt ker names.txt samo vsebuje vsa imena,
in želim, da izločijo vse tiste, ki niso edinstvene.
Torej, če sem naredil unikatnega names.txt, da ni čisto daj mi tisto, kar hočem
ker se podvaja imena so še vedno tam.
Zakaj je tako? Zakaj se ne uniq to, kar želim?
[Študent] V podvojeni vnosi niso [neslišno] >> Ja.
Ne pozabite, stran man za unikatnega pravi filter sosednje pripadajoči liniji.
Oni niso blizu, tako da jih ne bo filter.
Če bi jih razvrstite najprej uredi names.txt se bo dal vse podvojene vrstice skupaj.
Torej, zdaj je to neke vrste names.txt.
Bom želite uporabiti kot prispevek k unikatnega, kar je | uniq.
To mi daje Jožefa, RJ, Rob, Tommy
in želim uporabiti kot prispevek k wc-l,
ki se dogaja, da mi 4.
Kot piše tukaj, kaj cevovod lahko uporabite?
To lahko storite veliko stvari, kot je uporaba niz ukazov
kjer boste uporabili izhod iz ene ukaz kot prispevku k naslednji ukaz.
To lahko storite veliko stvari, veliko pametnih stvari.
>> Vprašanja?
Ok.
To je to, za cevi in ​​preusmeritev.
>> Zdaj gremo na dejanski stvari, kodiranje stvari.
Znotraj tega PDF, boste videli ta ukaz,
in boste želeli, da zaženete ta ukaz v vaši napravi.
wget je ukaz za ravno nekaj iz interneta, v bistvu,
Tako wget in ta naslov.
Če si šel na ta URL v brskalniku, bi prenos te datoteke.
Pravkar sem kliknil na to, da je naloženo datoteko za mene.
Toda pisanje wget te stvari znotraj terminala
je šele tekoč, da jo naložite na svoj terminal.
Imam section5.zip, in boste želeli, da razširite section5.zip,
ki se dogaja, da vam mapo z imenom section5,
ki se dogaja, da imajo vse datoteke ki jih bomo uporabljali danes notri.
Ker programi "Imena datotek kažejo, da si malo Otroški voziček,
Tako vaša naloga je, da ugotovimo, zakaj z gdb.
Ali so vsi jih prenesli / vedo, kako priti do njih prenesete
v svojo napravo? Ok.
>> Tek ./buggy1, bo rekel segmentacije napako (jedro po dampinških cenah),
kar koli boste dobili segfault, to je slabo.
Pod kakšnimi pogoji ste dobili segfault?
[Študent] Dereferenciranje null kazalec. >> Ja. Tako, da je en primer.
Dereferenciranje null kazalec, da boš dobil segfault.
Kaj segfault način je, da ste se dotika spomin ne smete dotika.
Torej Dereferenciranje null kazalec se dotika naslov 0,
in v bistvu so vsi računalniki danes povedal, da je naslov 0 spomin ne smete dotika.
Torej, to je, zakaj Dereferenciranje null kazalec rezultatov v segfault.
Ko se zgodi, da se ne inicializira kazalec, potem je za smeti vrednost,
in tako, ko poskušate ciljne datoteke, da se po vsej verjetnosti ste se dotika spomin
da je v sredi ničesar.
Če se zgodi, da bi dobili srečo in smeti vrednost
se je zgodilo, da kaže nekje na stack ali kaj podobnega,
potem ko dereference da kazalec, ki ste jih ni inicializirana,
ne bo nič narobe.
Ampak, če je poudariti, da, recimo, nekje med dimnik in kopica,
ali pa je poudaril le, da nekje je, da ni bil uporabljen za svoj program še ni,
potem ste se dotika spomin ne smete dotika in ga segfault.
Ko pišete rekurzivno funkcijo in recurses prevečkrat
in vaš dimnik raste prevelika in Sveženj trči v stvari
da ne bi bilo trka z, ste se dotika spomin ne smete dotika,
tako da segfault.
To je tisto, kar je segfault.
>> To je tudi razlog, da je enako, če imate niz, kot je -
gremo nazaj v prejšnjem programu.
V hello.c--Jaz samo dogaja, da bi nekaj drugega.
char * s = "Pozdravljen svet!";
Če uporabim * i = nekaj ali s [0] = "X";
zato poskrbite, zdravo. / zdravo, zakaj se je to segfault?
Zakaj se je to segfault?
Kaj bi lahko pričakovali zgodilo?
Če sem printf ("% s \ n", i); kaj bi lahko pričakovali, da se tiska?
[Študent] X zdravo. >> Ja.
Problem je, da ko se ugotovi niz, kot je ta,
s je kazalec, da se dogaja, da gredo na stack,
in kaj je kaže, da je ta niz, ki je vsebovana v bralnem pomnilniku.
Torej samo z imenom, bralni pomnilnik, bi dobili idejo
da če skušate spremeniti, kaj je v bralnem pomnilniku,
počneš nekaj, kar ne bi smeli početi s spominom in si segfault.
To je pravzaprav velika razlika med char * s in char s [].
Torej char s [], zdaj je ta niz se bo dal na sklad,
in sklad ni samo za branje, kar pomeni, da je treba delati to popolnoma v redu.
In to počne.
Ne pozabite, da ko sem naredil char * s = "Pozdravljen svet!", Je sam na kup
vendar opozarja, da s nekje drugje, in da se nekje drugje zgodi, da je samo za branje.
Ampak char s [] je le nekaj na kupu.
Torej, to je še en primer segfault dogaja.
>> Videli smo, da ./buggy1 povzročilo segfault.
V teoriji ne bi smeli gledati buggy1.c takoj.
Namesto tega bomo pogledamo skozi gdb.
Obvestilo, da ko prideš Napaka pri razčlenjenosti (jedro po dampinških cenah),
dobite te datoteke sem pozval jedra.
Če bomo ls-l, bomo videli, da je jedro je običajno zelo velika datoteka.
To je število bajtov datoteke, tako da izgleda, da je 250-nekaj kilobajtov.
Razlog za to je, da tisto, kar je dejansko Posmrtni
je, ko se program sesuje, stanje pomnilnika vašega programa
Samo dobi kopirali in prilepili v to datoteko.
To postane odvrgli v tej datoteki.
Ta program, medtem ko je bilo tekmovanje v teku, se je zgodilo, da imajo pomnilnika približno 250 kilobajtov,
in da je tisto, kar dobil vrgli v tej zadevi.
Zdaj si lahko ogledate na tej datoteki, če ne bomo gdb buggy1 jedro.
Mi lahko samo to gdb buggy1, in da bo le zagon gdb redno,
z buggy1 kot njegov vhodni datoteki.
Toda, če vam gdb buggy1 jedro, nato pa se bo posebej za začetek gdb
ga je videti na tej osnovni datoteki.
In praviš buggy1 pomeni gdb ve, da je ta osnovna datoteka prihaja iz buggy1 programa.
Torej gdb buggy1 jedro se bo takoj bi nam
kje se je zgodilo, da prekine programa.
Vidimo tukaj, program zaključi s signalom 11, Segmentacija napake.
Se zgodi, da bi videli linijo skupščino, ki verjetno ni zelo koristno.
Ampak, če vtipkate BT ali povratno sledenje, da se dogaja, da je funkcija
ki nam daje seznam naših sedanjih okvirih dimnika.
Torej backtrace '. Izgleda, da imamo le dva dimnih okvirje.
Prvi je naš glavni sklad okvir,
in 2. je sklad okvir za to funkcijo, da se zgodi, da je v,
ki izgleda kot da imamo le sestavljanja kodo.
Torej pojdimo nazaj v našo glavno funkcijo,
in za to lahko storimo okvir 1, in mislim, da smo lahko storite tudi določa,
vendar sem se skoraj nikoli ne dol - ali navzgor. Ja.
Gor in dol. Do vas pripelje do 1 žetonov okvir, kar vas je pripeljalo v kupu okvir.
Jaz ponavadi nikoli ne uporabljajte.
Pravkar sem rekel, posebej okvir 1, ki je šel na okvir z oznako 1.
Okvir 1 se dogaja, da nas pripelje na glavni okvir dimnik,
in pravi, tukaj je kode se zgodi, da bo pri.
Če smo želeli nekaj več vrstic kode, lahko rečemo seznam
in to se dogaja, da nam vse vrstic kode okrog njega.
Vrstica smo segfaulted na bilo 6:
if (strcmp ("CS50 kamenje", argv [1]) == 0).
Če ni očitno še ni, ga lahko dobite neposredno od tukaj, samo z razmišljanjem, zakaj je segfaulted.
Lahko pa si vzamete en korak naprej in reči: "Zakaj bi argv [1] segfault?"
Natisni Gremo argv [1], in izgleda, kot da je 0x0, ki je null kazalec.
Mi smo strcmping CS50 skale in nič, in da se bo segfault.
In zakaj je argv [1] ničen?
[Študent] Ker ni dobila nobenih argumentov v ukazni vrstici.
Ja. Mi ni dala nobenih argumentov v ukazni vrstici.
Torej ./buggy1 je le, da imajo argv [0], je ./buggy1.
To se ne dogaja, da imajo argv [1], tako da se bo segfault.
Ampak, če se namesto, jaz samo CS50, da se bo torej dobite D
ker to je tisto, kar je moral storiti.
Če pogledamo buggy1.c, je to naj bi natisniti "Dobiš D" -
Če argv [1] ni "CS50 skale", "Dobiš D", sicer "Dobiš!"
Torej, če želimo, moramo to primerjavo, kot pravi,
kar pomeni, da v primerjavi z 0.
Torej, argv [1] mora biti "CS50 kamenje".
Če želite to narediti v ukazni vrstici, morate uporabiti \ pobegniti prostor.
Torej CS50 \ skal in dobiš A!
Če tega ne boste storili, da backslash, zakaj to ne deluje?
[Študent] To je dve različni argumenti. >> Ja.
Argv [1], se bo CS50 in argv [2] se bo kamenje. Ok.
>> Zdaj ./buggy2 bo spet segfault.
Namesto, da bi ga odprli s svojo osnovno datoteko, bova odprla buggy2 neposredno,
Tako gdb buggy2.
Zdaj, če smo le teči naš program, potem bo to pravi program prejel signala SIGSEGV,
ki je segfault signal, in to se je zgodilo, da se zgodi.
Če pogledamo našo povratno sledenje, vidimo, da smo bili v funkciji oh_no,
ki je bil imenovan s funkcijo Dinky, ki je bil imenovan s funkcijo Binky,
ki je bil imenovan za glavnega.
Vidimo lahko tudi argumente, da te funkcije.
Trditev, da Dinky in Binky je bil 1.
Če naštejemo funkcije oh_no, vidimo, da se samo delaš oh_no char ** S = null;
* S = "BOOM";
Zakaj bi to uspelo?
[Študent] Ne, ne moreš dereference ničelno kazalec? >> Ja.
To je le, da je NULL, ne glede na to, da se zgodi, da char **
ki so, odvisno od tega, kako jo interpretirati, bi bilo kazalec na kazalec na niz
ali niz nizov.
To je NULL, tako da je * i Dereferenciranje null kazalec,
in tako se bo to crash.
To je eden od najhitrejših načinov, kako lahko morebiti segfault.
To je samo razglasitvi null kazalec in takoj segfaulting.
To je tisto, kar oh_no počne.
Če gremo eno sliko, potem pa se bomo dobili v funkcijo, ki se imenuje oh_no.
Moram narediti to.
Če ne vnesete ukaz in si zadeti nastopiti še enkrat,
da bo samo ponovi prejšnji ukaz, ki ste tekel.
Smo v okviru 1.
Ad tem okviru vidimo tukaj, je naša naloga.
Lahko seznam zadetkov znova, ali si lahko naredite seznam 20 in se bo seznam še več.
Funkcija Nakićen pravi, če je i 1, nato pa pojdite na funkcijo oh_no,
pa pojdite na Slinky funkcijo.
In vemo, i je 1, saj se zgodi, da vidim tu gor
Nakićen, da je bil imenovan s trditvijo 1.
Lahko pa tudi samo naj tiskam in bo rekel, da sem se 1.
Trenutno smo v Dinky, in če gremo še en okvir, smo vedeli, da bomo končali v Binky.
Up. Zdaj smo v Binky.
Ad to funkcijo - seznam iz pred polčasom me je prekinil -
je začel kot če jaz 0, potem bomo rekli oh_no, pa pokličite Nakićen.
Vemo, da sem bil 1, zato je pozval Nakićen.
In zdaj smo spet v glavnem, in glavna je le, da bo treba int i = rand ()% 3;
To je le, da bo dal naključno število, ki je bodisi 0, 1 ali 2.
To se dogaja, da pokličete Binky s to številko, in se vrnil 0.
Če pogledamo na to,
Samo sprehod skozi program ročno ne da bi jo takoj prikazovati,
da bi določil odmor točko na glavni, kar pomeni, da ko zaženete program
vaš program teče navzgor, dokler se ne dotakne break točko.
Torej, vodenje programa, deloval pa bo in potem bo zadel glavno funkcijo in preneha delovati.
Zdaj smo znotraj Glavni in korak ali naslednji nam bo prinesla naslednje vrstice kode.
To lahko naredite korak ali Naprej.
Hitting drugega, zdaj pa sem se lotil rand ()% 3, tako da lahko natisnete vrednost i,
in bo rekel, da sem se 1.
Zdaj to ne glede na to, ali bomo uporabili naslednji ali korak.
Mislim, da je važno v prejšnjem, vendar pa bi želeli uporabljati naslednji.
Če bomo uporabili korak, smo korak v funkciji, kar pomeni pogled na stvar dejansko
ki se dogaja znotraj Binky.
Če uporabimo drugo, potem to pomeni, da gredo čez funkcijo
in pojdite na naslednjo vrstico kode v naše delovanje.
Tukaj na tej liniji, sem bil v katerih je pisalo rand ()% 3;
če sem korak, bi šel v izvajanje rand
in poglej, kaj se tam dogaja, in sem lahko korak skozi funkcijo rand.
Ampak ne skrbi funkcijo rand.
Želim samo, da gredo na naslednjo vrstico kode v glavnem, zato sem uporabo naslednje.
Ampak zdaj mi ni vseeno glede Binky funkcijo, zato želim, da korak v to.
Zdaj sem v Binky.
Prva vrstica kode je reči, če (i == 0), jaz bi naredili korak,
vidimo, da končajo na Dinky.
Če smo seznam stvari, vidimo, da je bilo preverjeno, i = 0.
i ni enak 0, zato je šel k drugemu pogoju,
ki se bo klic Dinky (i).
Dobiš lahko zamenjali.
Če samo pogledaš na teh progah, neposredno, morda mislite, če (i == 0),
v redu, potem pa sem naredil korak, zdaj pa sem na Dinky (i),
si morda mislite, da je pomenilo, i = 0, ali kaj podobnega.
Ne samo pomeni, da ve, da lahko neposredno držijo linije Dinky (i).
Ker jaz ne 0, naslednji korak ne bo končala na drugem.
Sicer ni postavka, da se bo ustavil na.
To je le, da bo šel v naslednjo vrstico je dejansko lahko izvrši, kar je Nakićen (i).
Vstopanje v Dinky (i), vidimo, če (i == 1).
Vemo, i = 1, tako da, ko stopimo vemo, da bomo končali v oh_no
ker je i = 1 pokliče funkcijo oh_no, ki jo lahko naredimo korak v,
, ki se bo postavila char ** i = na NULL in takoj »BOOM«.
In potem je dejansko videti na izvajanje buggy2,
to, sem se ravno naključno število - 0, 1 ali 2 - klicanje Binky,
ki je 0, če sem pa poziva oh_no, sicer pa poziva Nakićen, ki pride gor.
Če je i 1, klic oh_no, pa pokličite slinky, ki prihajajo sem gor,
če je i 2, pokličite oh_no.
Sploh ne mislim, da je tako -
Ali kdo vidi način, da bi ta program, ki ne bo segfault?
Ker, če sem kaj spregledal, če sem na 0, boste takoj segfault,
pa greš na funkcijo, ki je, če sem si segfault 1,
pa greš na funkcijo, če je i 2 lahko segfault.
Torej, ni važno, kaj si naredil, ti segfault.
>> Mislim, da en način pritrditve, da bi bilo namesto dela char ** S = NULL,
lahko bi malloc prostor za to vrvico.
Lahko bi naredil malloc (sizeof) - sizeof kaj?
[Študent] (char) * 5? >> Ali to zdi v redu?
Jaz sem ob predpostavki, da bo to delovalo, če bi dejansko tekel, vendar to ni tisto, kar sem iskal.
Pogled na vrsti je. Naj dodamo int *, zato int * x.
Jaz bi naredil malloc (sizeof (int)).
Ali pa, če sem hotel niz 5, bi to storil (sizeof (int) * 5);
Kaj, če imam notr? **
Kaj bi jaz malloc?
[Študent] Velikost kazalca. >> Ja. (Sizeof (int *));
Ista stvar tukaj.
Hočem (sizeof (char *));
To se dogaja, da dodelitev prostora za kazalec, ki kaže na "boom".
Ne rabim za dodelitev prostora za "boom" sam
saj to je v bistvu enaka, kar sem rekel prej
od char * x = "boom".
»BOOM« že obstaja. To se zgodi, da obstaja v bralni regiji pomnilnika.
Ampak to že obstaja, kar pomeni, da te kode, če je je char **
potem * s char * in ste o tem char * opozoriti na "boom".
Če bi želel, da bi kopirali "boom" v S, potem bi morali dodeliti prostor za s.
Jaz bom * i = malloc (sizeof (char) * 5);
Zakaj 5?
Zakaj ne 4? Izgleda, da "boom" je 4 znake. >> [Študent] ničen učinek.
Ja. Vse vaše strune bodo potrebovali null značaj.
Zdaj lahko naredite nekaj takega strcat - Kaj je funkcija za kopiranje niz?
[Študent] KPJ? >> Strcpy.
Človek strcpy.
Torej strcpy ali strncpy.
strncpy je nekoliko varnejši, saj lahko natančno določite, koliko znakov,
ampak tukaj ni pomembno, saj vemo.
Torej strcpy in pogled v argumentih.
Prvi argument je naš cilj.
Drugi argument je naš vir.
Bomo kopirali v našo destinacijo * S kazalec "boom".
Zakaj bi si želeli, da to stori s strcpy namesto samo tisto, kar smo imeli pred
od * s = "BOOM"?
Obstaja razlog, da si morda želeli, da to storijo, a kaj je to razlog?
[Študent] Če želite nekaj spremeniti v "boom". >> Ja.
Zdaj bom lahko naredil kaj takega S [0] = "X";
ker s točke na kup in da je prostora na kup, da je obrnjena na
je kazalec več prostora na kup, ki je shranjevanje "boom".
Torej je to kopija "boom", ki se hranijo v kup.
Obstajata dva izvoda tehnično "boom" v našem programu.
Tukaj je prvi, ki je samo zaradi te "boom" konstanta niza,
in drugo kopijo "boom", strcpy ustvaril kopijo "boom".
Vendar pa je kopija "boom", ki se hranijo na kup in kup si svoboden spremeniti.
Kup ni samo za branje, tako da pomeni, da je s [0]
se dogaja, da vam spremeni vrednost "boom".
To se dogaja, da vam lahko spremenite te znake.
>> Vprašanja?
Ok.
>> Selitev na buggy3, kaj je gdb buggy3.
Pravkar smo ga zaženete in vidimo, dobimo segfault.
Če bomo 'backtrace, obstajata le dve funkciji.
Če gremo v našo glavno funkcijo, smo videli, da smo segfaulted na tej progi.
Torej samo gledaš na to progo, za (int vrstica = 0; fgets ta stvar ni enaka NULL;
vrstica + +).
Naš prejšnji okvir je bil imenovan _IO_fgets.
Videli boste, da je veliko z vgrajeno v funkcijah C,
da ko prideš segfault, bo zelo skrivnosten imena funkcij
kot je to _IO_fgets.
Ampak to se dogaja, da se nanašajo na ta razpis fgets.
Nekje notri, smo segfaulting.
Če pogledamo argumente za fgets, lahko natisnete buffer.
Naj natisnete - Oh, ne.
Tiskanje ne bo delovalo točno tako, kot želim, da bi.
Oglejmo si dejansko programa.
Buffer je razporeditve znakov. To je znak array 128 znakov.
Torej, ko rečem natisni buffer, da se bo za tiskanje 128 znakov
Mislim, da je kar, kar se pričakuje.
Kaj sem iskal je tiskanje naslov pufra,
vendar to ni res, povej mi veliko.
Torej, ko sem slučajno rekel sem gor x hranilnik, da mi pokaže 0xbffff090,
ki lahko, če se spomnite od prej ali neki točki, Oxbffff kaže, da je sklad-ish regiji.
Sveženj ponavadi nekje začeti tik pod 0xc000.
Tako ga vidim ta naslov, sem vedel, da pufer se dogaja na kupu.
Ponoven svoj program, teči navzgor, varovalni smo videli, je to zaporedje znakov
da so precej nesmiselna.
Potem tiskanje datoteke, kaj slika izgleda?
[Študent] ničelna. >> Ja.
Datoteka je tipa FILE *, zato je kazalec,
in vrednost tega kazalca je nična.
Torej fgets se bo poskušal brati iz tega kazalca na posreden način,
ampak za dostop do tega kazalca, ga mora dereference.
Ali pa, da bi dostop, kar bi morala biti obrnjena k, ga dereferences.
Torej, to je Dereferenciranje null kazalec in ga sesutja.
Lahko bi ga ponovno tam.
Če si odmor v našem glavnem mestu in teče,
Prva vrstica kode je char * filename = "nonexistent.txt";
To naj bi precej velik namig, zakaj ta program ne.
Tipkanje poleg me pripelje na naslednjo vrstico, ko odprem datoteko,
in potem sem takoj dobil v naši liniji, kjer se, ko sem udaril drugega, da se bo segfault.
Ali kdo želel vreči ven, zakaj ne bi mi lahko segfaulting?
[Študent] Datoteka ne obstaja. >> Ja.
To naj bi bil namig
da se vedno, ko odprete datoteko, ki jo je treba preveriti, ali datoteka sploh obstaja.
Torej, tukaj, "nonexistent.txt";
Ko smo fopen ime datoteke za branje, nato pa smo morali reči
if (datoteka == NULL) in reči printf ("Datoteka ne obstaja!"
ali - še bolje - naziv), vrnitev 1;
Zdaj smo preverite, če je NULL
preden se dejansko nadaljuje in poskuša brati iz te datoteke.
Mi lahko remake samo da bi videli, da stvar deluje.
Sem nameraval vključiti v novo vrstico.
Torej, zdaj nonexistent.txt ne obstaja.
Vedno morate preveriti te stvari.
Vedno preverite, da vidim, če fopen vrne NULL.
Vedno preverite, da se prepričajte, da malloc ne vrne NULL,
ali pa si segfault.
>> Zdaj buggy4.c.
Tek. Ugibam, da to čaka na vnos ali morda neskončno zanka.
Ja, to je neskončna zanka.
Torej buggy4. Zdi se, kot da smo neskončno zanka.
Mi lahko razbije na glavnem vodijo naš program.
V gdb, dokler okrajšava boste uporabili, je nedvoumno
ali posebne okrajšave, ki jih ponujajo za vas,
potem lahko uporabite n uporabiti naslednje, namesto da bi tip iz naslednjega konca.
In zdaj, ko sem zadel n enkrat, lahko samo pritisnite tipko Enter, da gremo naprej
namesto da bi udaril n Enter Vpišite n, n Enter.
Zdi se, kot da sem v nekakšnem za zanke, ki se določa niz [i] na 0.
Izgleda, da nikoli ne bom rešil iz tega za zanke.
Če sem tiskam, tako da sem za 2, potem pa grem naprej.
Jaz bom tiskanje, i 3, potem bom šel naprej.
Jaz bom tiskanje in i je 3. Nato sem natisniti, i 4.
Pravzaprav natisni sizeof (array), tako da velikost matrike je 20.
Ampak izgleda, da je nekaj posebnega gdb ukaz za odhod dokler se kaj ne zgodi.
To je, kot določa pogoj o vrednosti spremenljivke. Ampak jaz se ne spomnim, kaj je.
Torej, če nadaljujem -
Kaj si rekel? Kaj si bruhati?
[Študent] Ali prikazati dodam - >> Ja. Torej prikaz morem pomagati.
Če bomo samo prikažem, bo dal gor, kaj je vrednost i je
tako da mi ni treba natisniti vsakič.
Če bomo kar naprej gremo naprej, vidimo, 0, 1, 2, 3, 4, 5, 0, 1, 2, 3, 4, 5, 0, 1, 2, 3, 4, 5.
Nekaj ​​se dogaja hudo narobe, in jaz se se ponastavi na 0.
Če pogledamo buggy4.c, vidimo vse, kar se zgodi, je int array [5];
for (i = 0; i <= sizeof (array); i + +)
array [i] = 0;
Kaj vidimo, da je tukaj narobe?
Kot namig, ko sem delal gdb buggy4 - kaj je glavni odmor, tek -
Nisem natisni sizeof (array) samo zato, da vidim, kaj je pogoj, če naj končno izbruhnila.
Kje sem? Sem teči?
Nisem še izjavo.
Torej tiskanje sizeof (array) in to je 20,
za katerega se pričakuje od mojega matrika velikosti 5 in je za 5 števil,
tako da bi celotno stvar je 5 * sizeof (int) bajti, kjer je sizeof (int) kaže, da je 4.
Torej, sizeof (array) je 20.
Kaj bi to lahko bilo?
[Študent] Delimo z sizeof (int). >> Ja, / sizeof (int).
Izgleda, da je še vedno težava. Mislim, da bi morala biti samo <
saj je precej vedno <in ne <=.
Zdaj pa pomislite, zakaj se je to dejansko prekinjena.
Ali kdo so ugibanja, zakaj sem bil ponastavi na 0 prek vsaki ponovitvi zanke?
Edina stvar, ki v notranjosti tukaj, da se dogaja, da je matrika [i] je pa nastavljen na 0.
Tako nekako to vrstico kode povzroča našo int i se določi na 0.
[Študent] Ali je mogoče, saj je nujni spomin na ta del i
ko misli, da je naslednji element array? >> [Bowden] Da.
Ko gremo po koncu našega niza,
nekako, da je prostor, ki smo nujnimi je nujni vrednost i.
In tako, če pogledamo v buggy4, prekinil glavno, tek,
dajmo tiskanje naslov i.
Videti je, da je bffff124.
Zdaj pa natisnite naslov niz [0]. 110.
Kaj pa [1]? 114.
[2], 118.
11c, 120. array [5] je bfff124.
Torej, matrike [5] ima isti naslov kot jaz, kar pomeni, da matrika [5] i.
Če imajo isti naslov, gre za isto stvar.
Torej, ko smo postavili niz [5] na 0, smo i Nastavitev na 0.
In če misliš o tem glede na kupu,
int i se najprej razglasi, kar pomeni, da sem dobil nekaj prostora na kupu.
Potem matrika [5], se razporedi tako kot 20 bitov se dodelijo na kupu.
Tako postane i dodeljena, potem se dodelijo teh 20 bajtov.
Torej, jaz se zgodi tik pred matrike,
in zaradi načina, kot sem rekel prejšnji teden, kjer je to tehnično stack raste navzdol,
Ko indeks v matriki, so zagotovljene, da bomo 0. položaj v matriki
Vedno se zgodi pred prvo mesto v matriki.
To je nekako, kako mi je narisal prejšnji teden.
Obvestilo, da je na dnu imamo naslov 0 in na vrhu imamo naslov Maks.
Sveženj je vedno raste navzdol.
Recimo, da smo i dodeliti.
Mi razdeliti celo jaz, kar pomeni, da naj samo povem, tukaj sem celo dobi dodeljena.
Potem smo dodelijo portfelj 5 števil, kar pomeni, da je pod, ki
saj je sklad narašča navzdol, se dodeli 5 te cela števila.
Ampak zato, ker o tem, kako nizi delo, si bomo zagotoviti, da prvo mesto v matriki
Vedno je naslov manj kot v drugem stvar v polje.
Torej matrika položaj 0 mora vedno zgoditi v spominu,
ker matrika položaj 1 je zgodilo po tem
in matrika položaj 2 je zgodilo po tem,
kar pomeni, da matrika položaj 0, bi se zgodilo nekje tukaj,
matrika položaj 1, da bi se zgodilo zgoraj
ker se gibljejo pomeni višje naslove, saj je največja naslov tukaj.
Torej niz [0], tukaj, array [1] tu gor, array [2] tu gor, array [3] tukaj.
Opazuj, kako preden smo namenili celo število i vse tja gor,
kot smo korak naprej in naprej v naši matriki, smo bližje in bližje našemu celo i.
Se pač zgodi, da matriko [5], ki je eno mesto izven našega niza,
je točno tam, kjer sem celo zgodilo, da se dodelijo.
Torej, to je točka, kjer se zgodi, da bo zadel prostor na kupu
, ki je bil namenjen za celo i, in smo nastavitve, ki na 0.
>> Tako, da deluje. Vprašanja? Ja.
[Študent] Pozabi. Ok.
[Študent] Kako lahko izognete te vrste napak?
Te vrste napak? Ne uporabljajte C, kot je vaš programski jezik.
Uporabite jezik, ki ima matrične meje kontrole.
Dokler ste previdni, morate samo, da ne grem mimo meja svojega polja.
[Študent] Torej tukaj, ko smo šli mimo meja svojega niza -
[Bowden] To je, če se stvari začnejo narobe. >> [Študent] V redu.
Dokler boste ostali v spominu, dodeljenega za vaše polje, ti si v redu.
Ampak C pa ni preverjanje napak. Če naredim matriko [1000], bo z veseljem samo spremeniti karkoli se zgodi -
Jasno je, da na začetku niza, nato se pozicije po 1000 in jo nastavi na 0.
To ne naredi nobene preverjanje, da oh, to ni dejansko imel stvari v njej 1000.
1000 je tako tistega, kar bi moral biti spreminjanje,
ker bo Java ali kaj boste dobili matriko iz indeksa igrišča
ali indeks izven igrišča izjeme.
To je razlog, zakaj veliko višjih jezikih ravni imajo te stvari
kjer je, če greš zunaj meja delčka, ne
tako da ne morete spremeniti stvari izpod vas
in potem gredo stvari veliko slabše, kot ravno izjemo
pravijo, da si šel po koncu niza.
[Študent] In zato smo pravkar spremenili <= na samo <? >> [Bowden] Ja.
To bi moralo biti <sizeof (array) / sizeof (int);
saj sizeof (array) je 20, vendar smo le želeli 5. >> [Študent] desno.
Še vprašanja? Ok.
>> [Študent] Imam vprašanje. >> Ja.
[Študent] Kakšna je dejanska matrika spremenljivka?
[Bowden] Kot kaj je matrika?
Array sam simbol.
To je samo naslov začetkom 20 bajtov, da se sklicujete.
Lahko si o njej mislijo kot kazalce, vendar je konstantno kazalec.
Takoj ko se zbirajo stvari, variabilni matrika ne obstaja več.
[Študent] Torej, kako najti velikost array?
Velikost matrike se nanaša na velikost tega bloka, ki se nanaša na ta simbol.
Ko sem naredil kaj takega printf ("% p \ n", niz);
kaj je prost.
Kaj sem naredil narobe?
Array "matrika" prijavljeno tukaj.
Oh, tukaj.
Jek je pameten, in to se zgodi opazil, da sem izjavil matriko kot 5 elementov
vendar sem indeksiranje na položaj 1000.
To lahko storite, da zato, ker so to le konstante.
Lahko le šel tako daleč opazil, da bom zunaj meja matrike.
Toda opazil prej, ko smo imeli i nepravilne,
ne more ugotoviti, koliko vrednosti lahko vzamem naprej,
tako da ne more določiti, da bom po koncu niza.
To je samo Jek biti pameten.
>> Ampak zdaj bi buggy4. Torej, kaj še delam narobe?
Kaže razglasitvi knjižnico "printf".
Grem želijo # include .
Ok. Zdaj teče buggy4.
Tiskanje vrednosti matrike kot sem tukaj, da bi ga natisnili kot kazalec
natisne nekaj, kar izgleda takole - bfb8805c - kar je nekaj naslov
da je v kup-ish regiji.
Array sama je kot kazalec, vendar to ni dejanski kazalec,
saj redno kazalca lahko spremenimo.
Array je le nekaj konstantna. Med 20 kosi spomin na začetek 0xbfb8805c naslov.
Torej bfb8805c s tega naslova +20--ali Mislim -20 -
je vse pomnilnika, dodeljenih za ta niz.
Array je spremenljivka sama ne shrani nikamor.
Ko ste prevajanje, prevajalnik - ročno val na to -
vendar bo prevajalnik enostavno uporabite, če ve, da je matrika.
To, da ne ve, kje se začne matrika,
in tako lahko vedno samo stvari na področju nadomestil iz tega začetka.
Ne potrebujemo spremenljivko samo za zastopanje matriko.
Toda, ko sem naredil nekaj takega int * p = niz, zdaj p je kazalec, ki kaže na to polje,
in zdaj p dejansko ne obstaja na kupu.
Sem brez sprememb str. Lahko naredim, p = malloc.
Tako se je prvotno poudaril niz, zdaj pa opozarja, da nekaj prostora na kup.
Ne morem malloc niza =.
Če Jek je pameten, bo kričal name pravico off kij.
Pravzaprav sem prepričan, gcc bi to preveč.
Torej matrika tipa "int [5]" ni prenosljiva.
Ne morete dodeliti nekaj matrično tip
ker matrika je le konstantna.
To je simbol, ki te navedbe 20 bajtov. Ne morem spremeniti.
>> [Študent] In kje je velikost matrike shranjeno?
[Bowden] To se ne shrani nikamor. To je, ko se pripravi.
Torej, če je velikost matrike shranjeno?
Uporabljate lahko samo sizeof (array) znotraj funkcije, ki je matrika sama prijavljeni.
Torej, če sem naredil nekaj funkcij, foo, in jaz (int polje [])
printf ("% d \ n", sizeof (array));
in potem dol kličem foo (array);
znotraj te funkcije - kaj je to teči.
To je Jek biti pameten znova.
Govori mi, da sizeof na matrično funkcija parameter
vrne velikost "int *".
To bi bilo napak, če to ni tisto, kar sem želel, da se zgodi.
Naj se dejansko izklopite Werror.
Opozorilo. Opozorila so v redu.
To bo še pripraviti tako dolgo, kot je opozorilo.
. / A.out bo tiskanje 4.
Opozorilo, da je bila ustvarjena, je jasen pokazatelj, kaj je šlo narobe.
Ta int matrika je le, da bo tiskanje sizeof (int *).
Tudi če sem dal vrsto [5] tukaj, je še vedno le, da bo tiskanje sizeof (int *).
Torej takoj, ko ga posredovati v funkciji, razlikovanje med polji in kazalci
je sploh ni.
To se zgodi, da je matrika, ki je bila razglašena na sklad,
ampak takoj, ko se peljemo to vrednost, da 0xbf bla, bla, bla, bla v tej funkciji,
potem je ta kazalec kaže na to polju na kupu.
To pomeni, da je sizeof uporablja le v funkciji, ki je bila razglašena matrika,
kar pomeni, da ko se pripravi to funkcijo,
Jek, ko gre skozi to funkcijo, vidi array je matrika int velikosti 5.
Torej se ji zdi sizeof (array). No, to je 20.
To je pravzaprav, kako sizeof v bistvu deluje skoraj v vseh primerih.
Sizeof ni funkcija, to je upravljavec.
Vi ne kliči sizeof funkcijo.
Sizeof (int), bo prevajalnik prevesti le, da je 4.
Razumeš? Ok.
>> [Študent] Torej, kaj je razlika med sizeof (array) v glavni in v foo?
To je zato, ker si rekel sizeof (polje), ki je tipa int *,
ker je matrika tukaj ni tipa int *, je int matrika.
>> [Študent] Torej, če si imel parameter v polju [] namesto int * array,
bi to pomenilo, da se lahko še vedno spremenite vrsto, ker zdaj je kazalec?
[Bowden] Tako? >> [Študent] Ja. Lahko spremenite niz v funkciji zdaj?
[Bowden] Lahko spremenite zaporedje v obeh primerih.
V obeh primerih vas prosimo, da reči, array [4] = 0.
[Študent] Vendar si lahko matrično točko za kaj drugega?
[Bowden] Oh. Ja. V vsakem primeru - >> [Študent] Ja.
[Bowden] Razlika med matrike [] in int * polje, je ni.
Dobite lahko tudi nekaj večdimenzionalno matriko tukaj
za nekatere priročno sintakso, vendar je še vedno le kazalec.
To pomeni, da sem svoboden narediti niz = malloc (sizeof (int)), sedaj pa točko nekje drugje.
Toda tako kot kako to deluje vedno in vedno,
spremenite to vrsto, da postane kaže na nekaj drugega
ne spremenite to vrsto dol, ker je kopija trditev,
to ni kazalec na te trditve.
In dejansko, tako kot več navedbo, da je popolnoma enaka -
smo že videli, kaj odtisov matrične tisk -
Kaj pa, če tiskamo naslov matrike ali naslov naslovu matrike
bodisi tistih?
Naj prezreti to.
Ok. To je v redu. To je zdaj teče. / A.out.
Tisk niz, nato pa tiskanje naslov niz, so ista stvar.
Array preprosto ne obstaja.
Ve, ko tiskate niz, tiskate simbol, ki se nanaša na teh 20 bajtov.
Tiskanje naslov niz, no, matrika ne obstaja.
To nima naslova, tako da natisne samo naslov teh 20 bajtov.
Takoj, ko se zbere navzdol, tako kot v vašem zbrali buggy4. / A.out,
array je ni.
Kazalci obstajajo. Polja ne.
Bloki pomnilnika, ki predstavljajo niz še vedno obstajajo,
ampak spremenljivka polje in spremenljivke te vrste ne obstajajo.
Tisti, ki so kot glavne razlike med nizi in kazalci
se takoj, ko se ti klici funkcij, ni nobene razlike.
Toda znotraj funkcije, ki je bila prijavljena array sama, sizeof deluje drugače
ker tiskate velikost blokov namesto velikosti tipa,
in ga ne morete spremeniti, ker je simbol.
Tiskanje stvar in naslov stvar natisne isto stvar.
In to je vse.
[Študent] Bi lahko rekli, da še enkrat?
Mogoče sem kaj zamudil.
Tisk polje in naslov sklopa natisne enako,
ker če tiskate kazalec v primerjavi naslov kazalca,
ena stvar natisne naslov, kaj kaže na,
drugi natisne naslov kazalca na kupu.
Spremenite lahko kazalec, da ne morete spremeniti matrično simbol.
In sizeof kazalec se bo natisnila velikost tega kazalca tipa.
Torej, int * p sizeof (p) se bo tiskanje 4,
ampak int array [5] natisni sizeof (array) bo tiskanje 20.
[Študent] Torej bo int array [5] natisniti 20? >> Da.
Zato notranjosti buggy4, ko je bilo nekoč sizeof (array)
To je delal i <20, ki pa ni tisto, kar smo želeli.
Želimo i <5. >> [Študent] Ok.
[Bowden] In takoj, ko se začne prenos v delovanju,
če smo int * p = array;
znotraj te funkcije, lahko uporabite v bistvu p in paleto v popolnoma enak način,
razen tega problema sizeof in spreminjajoče problem.
Ampak p [0] = 1; je enaka kot pravi niz [0] = 1;
In takoj, ko rečemo foo (array); ali foo (p);
znotraj funkcije foo, to je isti poziv dvakrat.
Ni razlike med tema dvema klicema.
>> Vsi dobro na to? Ok.
Imamo 10 minut.
>> Mi bomo poskušali priti skozi ta program Hacker Typer,
ta spletna stran, ki je izšel lansko leto ali kaj podobnega.
To je samo domneva, da se kot vnesete naključno in se natisne -
Karkoli se zgodi, da slika je naložena tako kot izgleda tipkanjem.
Izgleda kot neke vrste operacijskega sistema kode.
To je tisto, kar želimo izvajati.
Moral bi imeti binarno izvedljivo imenom hacker_typer
da se v enem samem argumentu, datoteka na "vrsto hacker."
Vodenje izvršljiv treba počistiti zaslon
in nato natisnete en znak iz spregledanih, ki so v spisu vsakič, ko uporabnik pritisne na tipko.
Torej, ne glede tipko pritisnete, mora zavreči in namesto tega natisne znak iz datoteke
da je argument.
Jaz bom precej povedal, kaj stvari, ki jih bomo morali vedeti so.
Vendar želimo, da preverite knjižnico termios.
Nikoli nisem uporabil to knjižnico v mojem življenju, zato je zelo minimalno namene.
Toda to se bo knjižnica lahko uporabimo, da mečejo znak, ki ga je prizadel
ko tipkate v standardu palcev
Torej hacker_typer.c in bomo želeli # include .
Če pogledamo na stran man za termios - Jaz sem ugibati, da je terminal OS ali kaj podobnega -
Ne vem, kako, da ga preberete.
Ob pogledu na to, se pravi, da se te 2 datoteke, tako da bomo storili.
>> Prva stvar, prvič, želimo, da bi v enem samem argumentu, ki je datoteko moramo odpreti.
Torej, kaj bi rad naredil? Kako preverite, da imam en argument?
[Študent] Če argc je enak. >> [Bowden] Ja.
Torej, če (argc = 2!) Printf ("Uporaba:% s [odpreti datoteko]").
Torej, zdaj, če sem teči ta ne zagotavlja drugo trditev - oh, rabim novo linijo -
boste videli, da piše uporaba: /. hacker_typer,
in potem se drugi argument je datoteka želim odpreti.
No, kaj naj storim?
Želim brati iz te datoteke. Kako brati iz datoteke?
[Študent] Odprete ga najprej. >> Ja.
Torej fopen. Kaj fopen videti?
[Študent] datoteke. >> [Bowden] datoteke se bo argv [1].
[Študent] In potem, kaj želite storiti z njim, tako da - >> [Bowden] Ja.
Torej, če ni spomnil, si lahko naredil človek fopen,
če se bo char * pot, kjer pot naziv,
char * mode.
Če se zgodi, da se ne spomnim, kaj je način, potem si lahko ogledate način.
Znotraj priročnikov, znak slash je tisto, kar lahko uporabite za iskanje stvari.
Torej, sem tip / način za iskanje načina.
n in N, kar lahko uporabite, da skozi cikel iskalnih zadetkov.
Tukaj piše točk v načinu argumentov v niz
začenši z eno od naslednjih zaporedij.
Torej r, Odpri besedilno datoteko za branje. To je tisto, kar želimo narediti.
Za branje, in želim, da za shranjevanje.
Stvar se bo FILE *. Zdaj, kaj hočem narediti?
Daj mi sekundo.
Ok. Zdaj, kaj hočem narediti?
[Študent] Preverite, če je NULL. >> [Bowden] Ja.
Vsakič, ko odprete datoteko, se prepričajte, da ste uspešno mogli odpreti.
>> Zdaj bi rad to naredil termios stvari, kjer želim najprej prebrati moje trenutne nastavitve
in razen tistih, ki v nekaj, potem želim, da spremenim svoje nastavitve
da mečejo vse znake, da sem tipa,
in potem hočem posodobiti teh nastavitev.
In potem na koncu programa, želim spremeniti nazaj v moje prvotne nastavitve.
Torej struct se bo tipa termios, in bom želel 2 teh.
Prvi se bo moje current_settings,
in potem boš moji hacker_settings.
Najprej bom želite shraniti svoje trenutne nastavitve,
potem grem želite posodobiti hacker_settings,
nato pa pot na koncu mojega programa, želim, da se vrne na trenutne nastavitve.
Torej, shranite trenutne nastavitve, tako da deluje, mi človek termios.
Vidimo, da imamo to int tcsetattr, int tcgetattr.
Grem mimo v struct termios njegov kazalec.
Pot bo to videti, je - I've že pozabil, kaj se je imenoval funkcijo.
Kopirajte in prilepite.
Torej tcgetattr, potem pa želim prenesti v struct, da sem shranite podatke,
, ki se bo current_settings,
in prvi argument je datoteka Deskriptor stvar, želim, da shranite atribute.
Kaj je datoteka deskriptor je kot kadar koli odprete datoteko, da postane datotečni deskriptor.
Ko sem fopen argv [1], da dobi deskriptorju datoteke, ki ste referenciranja
, če želite prebrati ali pisati.
To ni datoteka deskriptor želim tukaj uporabiti.
Obstajajo tri datoteke deskriptorji imate privzeto,
ki so standard v, standard ven in standardna napaka.
Privzeto je, da mislim, da je standard v 0, ki je standardna 1 in 2 je standardna napaka.
Torej, kaj želim spremeniti nastavitve?
Rad bi spremenil nastavitve, ko sem zadel značaj,
Želim, da bi vrgel proč značaj, namesto da bi ga natisnili na platno.
Kaj tok - standard, standardni izhod, ali standardna napaka -
se odziva na stvari, ko sem tipa na tipkovnici? >> [Študent] Standard noter >> Ja.
Tako sem lahko naredila nobene 0 ali lahko storim stdin.
Grem na current_settings standardnih noter
>> Zdaj hočem posodobiti teh nastavitev,
tako da najprej bom skopirala v hacker_settings kakšne so moje current_settings so.
In kako konstrukti delo bo le kopija.
Ta kopije vseh področjih, kot bi lahko pričakovali.
>> Zdaj hočem, da posodobitev nekaterih področjih.
Če pogledamo termios, bi morali prebrati veliko tega
Samo da vidim, kaj bi si želeli iskati,
ampak zastav jih boste želeli iskati, so odmev,
Tako ECHO znakov vhodnih Echo.
Najprej želim set - I've že pozabili, kaj so polja.
To je tisto, kar struct izgleda.
Torej načinov vnosa mislim, da želimo spremeniti.
Bomo pogled na rešitev, se prepričajte, da je tisto, kar želimo spremeniti.
Želimo spremeniti lflag, da se prepreči da bi morali pogledati skozi vse to.
Želimo, da spremenite lokalne načine.
Ti bi morali prebrati skozi to celotno stvar, da bi razumeli, kje vse pripada
da želimo spremeniti.
Ampak to je znotraj lokalne načine, kam gremo, da želijo to spremeniti.
Torej hacker_settings.cc_lmode je, kako se imenuje.
c_lflag.
To je, če gremo v bitni operaterjev.
Mi smo nekako izven časa, ampak bomo šli skozi to hitro.
To je, če gremo v operaterji bitni,
kjer mislim, da sem rekel, enkrat dolgo nazaj, ko ste začeli, ki se ukvarjajo z zastavami,
boste uporabljali bitni strojniku veliko.
Vsak bit v zastavo ustreza neke vrste vedenja.
Torej, tukaj je ta zastava ima kup različnih stvari, kjer je vse od njih pomenijo nekaj drugega.
Toda tisto, kar želim storiti, je le izklopiti bit, ki ustreza ECHO.
Torej, da bi se to spremenilo off jaz & = ¬ ECHO.
Mislim, da je kot tECHO ali kaj podobnega. Grem še enkrat preveriti.
Lahko ga termios. To je samo odmev.
ECHO bo še en košček.
¬ ECHO bo pomenilo vsi biti nastavljeni na 1, kar pomeni, da so vse oznake so na true
razen ECHO bit.
Z konča svoje lokalne zastave s tem, to pomeni, da vse zastave, ki so trenutno določene na true
bo še vedno nastavljena na true.
Če je moja ECHO zastave nastavljena na true, potem je to nujno nastavljena na false v ECHO zastavo.
Torej, ta vrstica kode preprosto izklopi ECHO zastavo.
Drugi vrstic kode, bom kopirati jim je v interesu časa, nato pa jih razložiti.
V rešitvi, je dejal 0.
Verjetno je bolje, da se izrecno povedati stdin.
>> Obvestilo, da sem tudi početje ECHO | icanon tukaj.
Icanon nanaša na nekaj ločenega, kar pomeni, kanonično način.
Kaj pomeni canonical način je ponavadi, ko tipkate iz ukazno vrstico,
standard ne obdeluje ničesar, dokler ne dosežete vrstico.
Torej, ko vam GetString, vnesete kup stvari, potem ste zadeli vrstico.
To je, ko je bilo poslano v skladu s standardom noter
To je privzeta nastavitev.
Ko izklopite kanonično način, zdaj vsak znak, ko pritisnete
se dobi kaj predela, ki je običajno vrste slabo, ker je počasi obdelali te stvari,
zato je dobro, da se omili v celotnih linij.
Ampak rad vsak znak, ki se obdelujejo
ker ne želim, da počakate, da sem zadel novo vrstico
preden jih obdeluje vse znake sem bil tipkanje.
Ta izklopi kanonično način.
Ta stvar pomeni samo, ko je dejansko obdeluje znakov.
To pomeni, da jih obdelajo takoj, takoj, ko sem jih vnesete, jih obdeluje.
In to je funkcija, ki se posodablja svoje nastavitve za standard v,
in TCSA pomeni to prav zdaj.
Druge možnosti so počakati, dokler se obdelajo vse, kar je trenutno na potoku.
To sploh ni pomembno.
Ravno zdaj spremenim svoje nastavitve za vse, kar je trenutno v hacker_typer_settings.
Mislim, da so jo imenovali hacker_settings, tako da je spremenila.
Spremenite vse do hacker_settings.
>> Zdaj na koncu našega programa bomo želeli vrniti
s tem, kar je trenutno znotraj normal_settings,
ki se bo šele izgledal & normal_settings.
Obvestilo sem se niso spremenili vse moje normal_settings od prvotno dojemaš.
Potem se jih samo spremeniti nazaj, sem jih posredovali nazaj na koncu.
To je bila posodobitev. Ok.
>> Zdaj notranjosti tukaj bom samo razložiti kodo v interesu časa.
Saj ne, da je veliko kode.
Vidimo beremo znak iz datoteke. Poklicali smo ga f.
Sedaj lahko človek fgetc, ampak kako fgetc se bo delo
je samo, da se bo vrnil znak, ki ste ga pravkar prebral ali EOF,
ki ustreza koncu datoteke ali nekaj napak dogaja.
Mi smo zanka, nadaljuje, da se glasi en znak iz spisa,
dokler ne bo zmanjkalo črk za branje.
In medtem, ko delamo, da bomo čakali na en znak iz standarda palcev
Vsakič vnesete nekaj v ukazni vrstici,
da je branje v lik iz standarda noter
Potem je samo putchar bo dal znak beremo tu gor iz spisa v standardni izhod.
Lahko človek putchar, vendar je samo polaganje v skladu s standardom ven, to je, da se tiskanje značaja.
Lahko tudi samo ne printf ("% c", c); isto idejo.
To bo naredil večino našega dela.
>> Zadnja stvar, boste želeli storiti, je le fclose našo datoteko.
Če ne fclose, da je pomnilnika.
Želimo fclose datoteko smo sprva odprli, in mislim, da je to.
Če naredimo, da že imam probleme.
Pa poglejmo.
Kaj pa pritožujejo?
Pričakovan "int", ampak argument je tipa "struct _IO_FILE *".
Bomo videli, če deluje.
Dovoljeno samo v C99. Augh. Ok, da hacker_typer.
Zdaj smo dobili bolj uporabne opise.
Torej, uporabite črno identifikator "normal_settings".
Nisem klical, da normal_settings. Poklical sem ga current_settings.
Torej, kaj je vse to spremeniti.
Zdaj gre mimo argument.
Naredil bom to 0, za zdaj.
Ok. . / Hacker_typer cp.c.
Prav tako ni jasno, zaslon na začetku.
Vendar pa lahko ozremo na zadnji sklop problemov, kako ste počistiti zaslon.
To je samo nekaj znakov tiskanje
pa to je to, kar želim storiti.
Ok.
In razmišljal o tem, zakaj je to potrebno, da je 0 namesto standardnega vhoda,
ki jih je treba opredeliti # 0,
To se pritožuje, da je -
Prej, ko sem rekel, da je datoteka deskriptorjev, nato pa imate tudi svojo datoteko *,
Datotečni deskriptor je samo ena celo število,
ker FILE * ima cel kup stvari, povezane z njo.
Razlog moramo reči 0 namesto standardnega vhoda
je, da je stdin FILE * kar opozarja na stvari, ki se sklicujete datotečnega deskriptorja 0.
Torej tudi tu gor, ko sem naredil fopen (argv [1], sem že DATOTEKE * nazaj.
Ampak nekje v tej datoteki * je stvar, ki ustreza datoteke deskriptorjev za te datoteke.
Če pogledate na stran man za odprt, tako da mislim, da boste morali narediti človek 3 odprta - nope -
Človek 2 odprta - ja.
Če pogledate na stran za odprt, odprt je kot nižji ravni fopen,
in to je dejansko vrnil datotečnega deskriptorja.
fopen pa kup stvari na vrhu odprta,
ki je namesto vračanja le, da datoteka deskriptor vrne celoten spis * kazalec
Notranjost, ki je naš mali datoteke deskriptor.
Tako standard se nanaša na stvar, FILE *,
ker se nanaša le 0 datoteke standarda deskriptor sam po sebi.
>> Vprašanja?
[Smeh] Odpihnil skozi to.
V redu. Končali smo. [Smeh]
>> [CS50.TV]