[Powered by Google Translate] [5 jakso - More Comfortable]
[Rob Bowden - Harvardin yliopisto]
[Tämä on CS50. - CS50.TV]
>> Kuten sanoin sähköpostitse, on paljon asioita, voit käyttää
muu kuin laite itse tehdä ongelman sarjaa.
Suosittelemme teet sen laitteen vain siksi voimme helpommin auttaa sinua
ja me tiedämme, kuinka kaikki on menossa töihin.
Mutta kuten yksi esimerkki, jossa voit tehdä asioita, jos vaikkapa sinulla ei ole pääsyä
että laite tai haluat työskennellä Science Center kellarissa -
joka todellisuudessa heillä laitetta liian -
Jos haluat työskennellä missä tahansa.
Yksi esimerkki on olet nähnyt / kuullut SSH?
SSH on pohjimmiltaan aivan yhteyden jotain.
Oikeastaan ​​nyt olen SSHed laitteeseen.
En koskaan työskentele suoraan laitteeseen.
Tässä on laite, ja jos katsotte tänne näet tämän IP-osoitteen.
En koskaan työskentele itse laite;
Olen aina tullut yli iTerm2 ikkunaan / pääteikkuna.
Voit SSH että IP-osoite, ssh jharvard@192.168.129.128.
Muistan, että joukko hyvin helposti, koska se on niin kiva kuvio.
Mutta kysyy minulta salasanaa, ja nyt olen laitteeseen.
Pohjimmiltaan tässä vaiheessa, jos avattu päätelaitteen sisällä itse laite,
Tämän liitännän, mutta voit käyttää sitä, on täsmälleen sama
kuten käyttöliittymän Käytän täällä, mutta nyt olet SSHed.
Sinun ei tarvitse SSH laitteeseen.
Yksi esimerkki toisessa paikassa voisit SSH on Olen melko varma olet oletuksena -
Oh. Isompi.
Kaikkien pitäisi olla oletuksena FAS tilinpäätöksen FAS palvelimiin.
Minulle, haluan SSH rbowden@nice.fas.harvard.edu.
Se tulee kysyä, että ensimmäistä kertaa, ja sanot kyllä.
Minun salasanaa vain olemaan minun FAS salasanaa.
Ja nyt, olen SSHed on mukava palvelimet, ja voin tehdä mitä haluan täällä.
Monet luokat saatat ottaa, kuten 124, ovat menossa lataat tavaraa täällä
todella lähettää ongelman sarjaa.
Mutta sano et pääse käyttämään laitetta.
Sitten voit tehdä asioita, kuten täällä sitä sanoa -
Tämä on vain meidän osassa kysymyksiä.
Se pyytää sinua tekemään tämän laitteen.
Sen sijaan minä vain tehdä sen palvelimelle.
Aion purkaa se.
Ongelma tulee olemaan, että olet tottunut käyttämään jotain gedit
tai mitä sisällä laitteen.
Et aio olla, että FAS palvelimelle.
Se kaikki on vain olemaan tämän tekstuaalisen liitäntä.
Joten voit joko yhden, yrittää oppia tekstieditori, joka niillä on.
Heillä on Nano.
Nano on yleensä melko helppo käyttää.
Voit käyttää nuolia ja kirjoita normaalisti.
Joten se ei ole vaikeaa.
Jos haluat saada todella fancy voit käyttää Emacs,
joka luultavasti ei olisi pitänyt avata, koska en edes tiedä miten lopettaa Emacs.
Ohjaus X, Control C? Joo.
Tai voit käyttää Vim, joka on mitä käytän.
Ja niin ne ovat vaihtoehtoja.
Jos et halua tehdä sitä, voit myös, jos tarkastellaan manual.cs50.net--
Oh.
Tietokoneella, voit SSH PuTTY,
jotka olet menossa tarvitse ladata erikseen.
Macissa voit vain oletuksena käytössä Terminal tai voit ladata iTerm2,
joka on kuin mukava, hieno terminaali.
Jos menet manual.cs50.net näet linkin Notepad + +,
joka on mitä voit käyttää tietokonetta.
Sen avulla voit SFTP alkaen Notepad + +, joka on pohjimmiltaan SSH.
Mitä tämä avulla voit tehdä on muokata tiedostoa paikallisesti,
ja sitten kun haluat tallentaa ne, se tallentaa nice.fas,
jossa voit käyttää niitä.
Ja vastaavaa Mac tulee olemaan TextWrangler.
Joten sen avulla voit tehdä samoin.
Sen avulla voit muokata tiedostoja paikallisesti ja tallentaa ne nice.fas,
jossa voit käyttää niitä.
Joten jos olet koskaan jumissa ilman laitetta, sinun on nämä vaihtoehdot
Vielä tee ongelmaa sarjaa.
Yksi ongelma tulee olemaan, että et aio olla CS50 kirjasto
koska nice.fas ei oletuksena ole tätä.
Voit joko ladata CS50 kirjasto -
En mielestäni tarvitse, että tässä vaiheessa.
Voit joko ladata CS50 kirjastosta ja kopioi se nice.fas,
tai luulen tässä vaiheessa emme käytä sitä enää muutenkaan.
Tai jos teemme, voit toistaiseksi vaihda se
toteutuksia toimintojen CS50 kirjaston tapauksessa.
Niin että ei pitäisi olla paljon rajoituksia.
Ja se siitä.
>> Menen takaisin laitteeseen nyt, me teemme kaiken laitteen.
Tarkasteltaessa meidän osassa kysymyksiä, alussa, niin kuin sanoin email,
meidän on puhuttava yhdellä lyhyellä sinun piti katsoa.
Olemme suuntaamaan & Putket ja nämä kolme kysymystä.
>> Jonka virta ei toimii kuten printf kirjoittaa oletuksena?
Niin stream. Mikä on virta?
Virta on pohjimmiltaan kuin se on vain muutamia -
Se ei ole edes lähde 1s ja 0s.
Virta se pyytää tässä on vakiona pois.
Ja niin standardi ulos on virta, että kun kirjoittaa sitä,
se näkyy näytössä.
Standard ulos, jonka virta, se tarkoittaa vain kirjoittaa 1s ja 0s siihen,
ja toinen pää standardin ulos vain lukee että virrasta.
Se on vain merkkijono 1s ja 0s.
Voit kirjoittaa virtoja tai voit lukea puroihin
riippuen siitä, mitä stream todellisuudessa on.
Kaksi muuta Oletuksena purot ovat vakiona ja keskivirhe.
Vakiona on aina et GetString, se odottaa sinua syöttää tavaraa.
Joten se odottaa teitä, se on oikeastaan ​​odotti standardin,
joka on todella mitä saat, kun kirjoitat näppäimistöllä.
Sinä kirjoitat tavallisiin sisään
Keskivirhe on periaatteessa vastaa standardin ulos,
mutta se on erikoistunut että kun tulostat keskivirhe,
sinun pitäisi vain tulostaa virheilmoituksia että
joten voit erottaa säännöllisesti viestejä tulostetaan näytölle
vs. virheilmoituksia riippuen siitä menivät standardin ulos tai keskivirhe.
Tiedostoja myös.
Standard ulos, standardi, ja keskivirhe ovat vain erityisiä virtoja,
mutta oikeastaan ​​minkä tahansa tiedoston, kun avaat tiedoston, se tulee tavuvirrasta
jossa voit vain lukea tuosta virrasta.
Sinä, suurimmaksi osaksi, voi vain ajatella tiedoston tavuvirrasta.
Joten mitä virtoja ne kirjoita oletuksena? Standard ulos.
>> Mitä eroa on> ja >>?
Onko kukaan katsella videota etukäteen? Okei.
> Tulee olemaan miten ohjaat tiedostoihin,
ja >> aikoo myös suunnata tulosteen tiedostoja,
mutta se sen sijaan tulee liittää tiedostoon.
Esimerkiksi sanokaamme Minulla sattuu olemaan dict täällä,
ja ainoa tavaraa sisällä dict on kissa, kissa, koira, kala, koira.
Yksi komento, että sinulla on komentorivi on kissa,
joka on juuri menossa painoon, mitä on tiedosto.
Joten kun sanon kissa dict, se tulee tulostaa kissa, kissa, koira, kala, koira. Siinä kaikki kissa tekee.
Tämä tarkoittaa, että se painettu standardin ulos kissa, kissa, koira, kala, koira.
Jos minä sen sijaan halua ohjata että tiedostoon, voin käyttää> ja ohjaa sen mitä tiedosto on.
Soitan tiedosto tiedosto.
Joten nyt jos ls, näen olen uusi tiedosto nimeltä tiedosto.
Ja jos avaan sen, se tulee olemaan mitä kissa laittaa komentoriviltä.
Joten nyt jos teen sen uudelleen, niin se tulee suunnata tulosteen tiedostoon,
ja aion olla täsmälleen sama asia.
Joten teknisesti se kokonaan syrjäytti mitä meillä oli.
Ja näemme jos muutan dict, otin koiran.
Nyt jos kissa dict osaksi tiedoston uudelleen, aiomme saada uuden version koira poistettu.
Joten se täysin korvaa sitä.
Sen sijaan, jos käytämme >>, se tulee liittää tiedostoon.
Nyt, avaa tiedosto, näemme meillä on vain sama asia painetaan kahdesti
koska se oli siellä kerran, meidän liitteenä alkuperäiseen.
Niin, että mitä> ja >> tehdä.
Onko seuraava kysyä - Se ei kysy sitä.
>> Toinen, että meillä on <, joka jos> uudelleenohjaa standardin ulos,
<Aiotaan suunnata vakio sisään
Katsotaan, jos meillä on esimerkki.
En voi kirjoittaa yhden todella nopeasti.
Otetaan jokin tiedosto, hello.c.
Suhteellisen yksinkertainen tiedosto.
Haen vain merkkijonon ja sitten tulostaa "Hello" mitä merkkijono juuri tullut oli.
Joten varmista Hei sitten. / Hello.
Nyt se on kehotus minua tulla jotain,
mikä tarkoittaa sitä odottaa asioita on tullut standardi sisään
Joten anna mitä haluan tavallisiin sisään Olemme juuri menossa sanoa Hei, Rob!
Sitten se tulostetaan standardin ulos Hei, Rob!
Jos teen. / Hei ja ohjaa sitten,
nyt voit vain ohjata tiedostosta.
Joten jos laitan joissakin tiedoston txt, ja laitoin Rob,
jos juoksen Hei ja ohjaa sitten tiedoston txt osaksi. / Hei, se tulee sanoa Hei, Rob! välittömästi.
Kun se ensin saa GetString ja se odotti standardin,
standardi ei enää odottamassa näppäimistö tietojen saada kirjoittaa.
Sen sijaan olemme ohjataan standardin lukea tiedoston txt.
Ja niin se tulee lukea tiedoston txt, joka on vain viiva Rob,
ja sitten se tulee tulostaa Hei, Rob!
Ja jos halusin, voisin myös tehdä. / Hei <txt
ja sitten standardia että sen paino, joka on Hei, Rob!,
Voin ohjata että omaan tiedostoon.
Minä vain soittaa tiedoston Hei - Ei, en ole, koska se executable - txt2.
Nyt, txt2 tulee olemaan ulostulo. / Hello <txt, joka tulee olemaan Hei, Rob!
>> Kysymyksiä?
>> Okei. Joten tässä meillä on putki.
Putket ovat viimeinen yksikkö uudelleenohjaus.
>> Oh. Luulen yksi yksikkö uudelleenohjaus on jos sen sijaan> teet 2>,
joka on suuntaamalla keskivirhe.
Joten jos jotain meni keskivirhe, se ei saa panna txt2.
Mutta huomaa jos teen 2>, niin se on silti tulostuksen Hei, Rob! komentorivin
koska olen vain kohdentamalla keskivirhe, en suuntaamaan standardin ulos.
Keskivirhe ja standardi ulos ovat erilaisia.
Jos halusi todella kirjoittaa keskivirhe,
Sitten voisin muuttaa tämän olevan fprintf stderr.
Joten printf, oletuksena tulostaa standardin ulos.
Jos haluan tulostaa keskivirhe käsin, sitten minun täytyy käyttää fprintf
ja määrittää, mitä haluan tulostaa.
Jos sen sijaan tein fprintf stdout, niin se on pohjimmiltaan vastaa printf.
Mutta fprintf vakiovirhetulosteeseen.
Joten nyt, jos en ohjaa tämä otetaan txt2, Hei, Rob! edelleen saada tulostetaan komentoriviltä
koska se on menossa painettu vakiovirhetulosteeseen ja olen vain suuntaamalla standardin ulos.
Jos minä nyt uudelleenohjaus keskivirhe, nyt se ei tulosteta, ja txt2 tulee olemaan Hei, Rob!
Joten nyt, voit tulostaa todellisia virheitä keskivirhe
ja tulostaa säännöllisesti viestejä standardin ulos.
Ja niin kun suoritat ohjelman, voit suorittaa sen. / Hei tämäntyyppiset 2>
niin, että ohjelma tulee toimimaan normaalisti,
mutta virheilmoituksia että saat voit tarkistaa myöhemmin omassa virhelokiin,
niin virheet, ja katso sitten myöhemmin ja teidän virheet tiedosto on virheitä tapahtui.
>> Kysymyksiä?
>> Viimeisin on putki, jonka voit ajatella kuin ottaa standardin ulos yhden komennon
ja tekee siitä standardin seuraavan komennon.
Esimerkkinä tästä on kaiku on komentorivi juttu
joka on juuri menossa echo mitä laitoin sen väitettä. En laita lainausmerkkejä.
Echo blaa, blaa, blaa on juuri menossa painoon blaa, blaa, blaa.
Ennen kun sanoin täytyi laittaa Rob osaksi txt-tiedostona
koska en voi vain ohjata txt-tiedostoja, vaan, / jos toistan Rob
ja sitten putki sen. / Hei, jotka tekevät saman tyyppinen asia.
Tämä vie tuotos tämän komennon, kaiku Rob,
ja käyttämällä sitä tulo. / hello.
Voit ajatella sitä ensimmäisenä suunnata echo Rob tiedostoon
ja sitten syötetään. / Hei että tiedosto oli juuri ulos.
Mutta se vie tilapäisen tiedoston ulos kuvan.
>> Kysymyksiä tästä?
>> Seuraava kysymys tulee liittyä tähän.
Mikä putki voisit käyttää löytää useita ainutlaatuisia nimiä tiedosto nimeltä names.txt?
Komennot aiomme haluavat käyttää tässä ovat ainutlaatuisia, niin uniq, ja sitten wc.
Voit tehdä miehen uniq todella katsoa, ​​mitä se tekee,
ja se on juuri menossa suodattaa viereiseen rivejä syöttölokerosta.
Ja mies wc aikoo tulostaa rivinvaihto, sana ja tavu laskee kunkin tiedoston.
Ja viimeinen aiomme haluat käyttää, on lajitella,
joka on menossa juuri lajitella rivit txt-tiedosto.
Jos teen joitakin txt tiedoston, names.txt, ja se on Rob, Tommy, Joseph, Tommy, Joseph, RJ, Rob,
mitä haluan tehdä tässä löytää useita ainutlaatuisia nimiä tähän tiedostoon.
Joten mitä jos vastaus on? >> [Opiskelija] 4. >> Joo.
Sen pitäisi olla 4, sillä Rob, Tommy, Joseph, RJ ovat vain ainutlaatuisia nimiä tähän tiedostoon.
Ensimmäinen askel, jos en tee sanamäärä on names.txt,
Tämä on oikeastaan ​​kertoo minulle kaiken.
Tämä on todella tulostus - Katsotaan, mies wc - rivinvaihtoja, sanoja, ja tavu count.
Jos minä vain välitä riviä, niin voin vain tehdä wc-l names.txt.
Joten se vaihe 1.
Mutta en halua wc-l names.txt koska names.txt juuri sisältää kaikki nimet,
ja haluan suodattaa pois ei-ainutlaatuista niistä.
Joten jos en Uniq names.txt, että ei oikein anna minulle mitä haluan
koska kahdennettu nimet ovat edelleen olemassa.
Miksi näin? Miksi Uniq ei tee mitä minä haluan?
[Opiskelija] kaksoiskappaleet eivät [kuulumattomissa] >> Joo.
Muista man-sivulla uniq sanoo suodattimen vieressä rivejä.
He eivät vieressä, joten se ei suodata niitä.
Jos minä lajitella ensin järjestä names.txt tulee laittaa kaikki päällekkäiset linjat yhdessä.
Joten nyt sort names.txt että.
Aion halua käyttää sitä tulo Uniq, mikä on | uniq.
Se antaa minulle Joseph, RJ, Rob, Tommy,
ja haluan käyttää sitä tulo wc-l,
joka ei aio antaa minulle 4.
Kuten tässä sanotaan, mitä putki voisi käytät?
Voit tehdä monia asioita kuten käyttämällä useita komentoja
jos käytät ulostulo yhdestä komento syöttää seuraavan komennon.
Voit tehdä paljon asioita, paljon viisaita asioita.
>> Kysymyksiä?
Okei.
Se on se putkia ja uudelleenohjaus.
>> Nyt lähdemme varsinaiseen tavaraa, koodaus kamaa.
Inside tämän PDF näet tämän komennon,
ja sinun kannattaa suorittaa tämän komennon laitteesi.
wget on komento vain saada jotain Internet pohjimmiltaan
joten wget ja tämä URL.
Jos meni tämä URL selaimessasi, se lataa tiedoston.
Minä vain napsautti sen, niin se ladattu tiedosto minulle.
Mutta kirjallisesti wget että asia sisällä terminaalin
on juuri menossa ladata sen omaan terminaaliin.
Olen section5.zip, ja sinun kannattaa purkaa section5.zip,
joka aikoo antaa sinulle kansio nimeltä section5,
joka tulee olemaan kaikkien tiedostojen aiomme käyttää tänään sen sisälle.
Koska näiden ohjelmien tiedostojen nimiensämukaisesti he hieman buginen,
joten sinun tehtäväsi on selvittää, miksi käyttää GDB.
Onko kaikki ovat niitä ladannut / tietää miten saada ne ladattua
heidän laitteeseen? Okei.
>> Juoksu ./buggy1 se sano Segmentointi vika (core polkumyynnillä),
mikä tahansa saat segfault, se on huono juttu.
Missä olosuhteissa saat segfault?
[Opiskelija] Dereferencing nollaosoittimen. >> Joo. Niin, että on yksi esimerkki.
Dereferencing nollaosoittimen aiot saada segfault.
Mikä segfault tarkoittaa olet koskettaa muistia pitäisi olla koskematta.
Joten dereferencing nollaosoittimen koskettaa osoite 0,
ja pohjimmiltaan kaikki tietokoneet nykyään sanoa, että osoite 0 on muistia pitäisi olla koskematta.
Joten siksi dereferencing nollaosoittimen tuloksia segfault.
Kun satut olemaan alustaa osoittimen, niin se on roskaa arvo,
ja niin kun yrität dereference sitä, kaiken todennäköisyyden olet kosketat muistia
joka on keskellä ei mitään.
Jos satut onnekas ja roskat arvo
tapahtui viitata jonnekin pinoon tai jotain,
sitten kun dereference että osoitin joita et ole alustettu,
mikään ei mene pieleen.
Mutta jos se osoittaa vaikkapa jonnekin pino ja keko,
tai se osoittaa vain jostain, että ei ole käytetty ohjelma vielä,
Sitten olet koskettamalla muistia pitäisi olla koskematta ja sinä segfault.
Kun kirjoittaa rekursiivinen funktio, ja se recurses liian monta kertaa
ja pino kasvaa liian suureksi ja pinon törmää asioihin,
että se ei tule törmäystä, et kosketa muistia pitäisi olla koskematta,
joten segfault.
Tämä on mitä segfault on.
>> Se on myös samasta syystä, että jos sinulla on merkkijono kuten -
Mennään takaisin edelliseen ohjelmaan.
In hello.c--Olen juuri menossa tekemään jotain muuta.
char * s = "Hei maailma!";
Jos käytän * s = jotain tai s [0] = 'X';
joten varmista Hei,. / Hei, miksi se segfault?
Miksi tämä segfault?
Mitä odotat tapahtumaan?
Jos tein printf ("% s \ n", s); mitä odotat tulostaa?
[Opiskelija] X hei. >> Joo.
Ongelmana on, että kun julistaa merkkijonon, kuten tämä,
s on osoitin, joka on menossa pinoon,
ja mitä s on osoittaa tämä merkkijono, joka sisältyy lukumuistiin.
Eli vain nimi, lukumuisti, sinun pitäisi saada idea
että jos yrität muuttaa mitä vain luku-muisti,
teet jotain ei pitäisi tehdä muistilla ja sinä segfault.
Tämä on todella suuri ero char * s ja char s [].
Joten char s [], nyt tämä merkkijono aiotaan laittaa pinon
ja pino ei ole vain luku-eli tämän pitäisi toimia hienosäätää.
Ja se tekee.
Muista, että kun teen char * s = "Hello world!", S itsessään on pino
mutta s viittaa jonnekin muualle, ja että jossain muualla sattuu olemaan vain lukea.
Mutta char s [] on vain jotain pinoon.
Joten se on toinen esimerkki segfault tapahtumassa.
>> Näimme, että ./buggy1 johti segfault.
Teoriassa sinun pitäisi tarkastella buggy1.c välittömästi.
Sen sijaan me tarkastelemme sitä kautta GDB.
Huomaa, että kun saat Segmentointi vika (core polkumyynnillä),
saat tämän tiedoston tänne kutsutaan ydin.
Jos me ls-l, näemme, että ydin on yleensä aika iso tiedosto.
Tämä on monta tavua tiedoston, niin se näyttää se 250-jotain kilotavua.
Syynä tähän on se, että mitä core dump todellisuudessa on
on, kun ohjelma kaatuu, tila muistiin ohjelman
vain saa kopioida ja liittää tämän tiedoston.
Se saa polkumyynnillä tuohon tiedostoon.
Tämä ohjelma, kun se oli käynnissä, sattui olemaan muistin käyttö noin 250 kilotavua,
ja niin sitähän mutta polkumyynnillä tähän tiedostoon.
Nyt voit katsoa, ​​että tiedosto jos teemme gdb buggy1 ydin.
Voimme vain tehdä gdb buggy1, ja joka vain käynnisty gdb säännöllisesti,
käyttäen buggy1 sen syötetiedosto.
Mutta jos et gdb buggy1 ydin, niin se on nimenomaan aikoo käynnistää gdb
katsomalla, että ydintiedostoa.
Ja sanot buggy1 tarkoittaa gdb tietää että ydintiedostoa tulee buggy1 ohjelmasta.
Joten gdb buggy1 ydin aikoo välittömästi tuoda meille
missä ohjelmassa tapahtui lopettaa.
Näemme täällä Program päättyy signaalia 11, segmentointi vika.
Satumme näkemään linjan kokoonpano, joka todennäköisesti ei ole kovin hyödyllistä.
Mutta jos kirjoitat BT tai backtrace, joka tulee olemaan funktio
joka antaa meille luettelon nykyiseen pinon kehyksiä.
Niin backtrace. Se näyttää meillä on vain kaksi pino kehyksiä.
Ensimmäinen on tärkein pinokehys,
ja toinen on pinokehys tätä toimintoa varten, että me sattuvat olemaan,
joka näyttää meillä on vain kokoonpano koodi.
Mennään takaisin meidän päätehtävä,
ja tehdä, että me voimme tehdä runko 1, ja uskon, että voimme myös tehdä alas,
mutta en juuri koskaan tee alas - tai ylöspäin. Joo.
Ylös ja alas. Jopa tuo yhden pinokehys, alas tuo alas pinokehys.
Olen taipuvainen koskaan käytä sitä.
En vain nimenomaan sanoa rungon 1, joka on mene runkoon merkitty 1.
Kehys 1 aikoo tuoda meidät tärkeimmät pinokehys,
ja tässä sanotaan koodirivi satumme olemaan.
Jos haluaisimme pari lisää riviä koodia, voimme sanoa luettelossa,
Ja se antaa meille kaikille koodia sen ympärille.
Linja meillä segfaulted osoitteessa oli 6:
jos (strcmp ("CS50 kiviä", argv [1]) == 0).
Jos se ei ole selvää vielä, saat sen suoraan täältä vain ajattelemalla miksi se segfaulted.
Mutta voimme ottaa sen askeleen pidemmälle ja sanoa, "Miksi argv [1] segfault?"
Katsotaanpa print argv [1], ja se näyttää sen 0x0, mikä on nollaosoittimen.
Olemme strcmping CS50 kiviä ja nolla, ja niin että menee segfault.
Ja miksi argv [1] null?
[Opiskelija] Koska emme anna sille mitään komentorivin argumentteja.
Joo. Emme anna sille mitään komentorivin argumentteja.
Joten ./buggy1 vain olemaan argv [0] olla ./buggy1.
Se ei tule olemaan argv [1], niin että menee segfault.
Mutta jos sen sijaan, minä vain CS50, se tulee sanoa Saat D
koska se mitä sen pitäisi tehdä.
Tarkasteltaessa buggy1.c, se pitäisi tulostaa "Saat D" -
Jos argv [1] ei "CS50 rocks", "Saat D", muuten "Saat!"
Joten jos haluamme, me tarvitsemme tätä verrata niin totta,
mikä tarkoittaa, että sitä voidaan verrata 0.
Joten argv [1] on oltava "CS50 kiviä".
Jos haluat tehdä komentorivillä, sinun täytyy käyttää \ paeta tilaa.
Joten CS50 \ kiviä ja saat!
Jos et tee kenoviiva, miksi tämä ei toimi?
[Opiskelija] On kaksi eri argumentteja. >> Joo.
Argv [1] tulee olemaan CS50, ja argv [2] tulee olemaan kiviä. Okei.
>> Nyt ./buggy2 on menossa segfault uudelleen.
Avaamisen sijaan se sen ydin tiedoston, me vain avata buggy2 suoraan,
niin GDB buggy2.
Nyt jos me vain ajaa ohjelmaamme, niin se tulee sanoa Program vastaanotetun signaalin SIGSEGV,
joka on segfault signaali, ja tämä on silloin, kun se tapahtui tapahtua.
Tarkasteltaessa meidän backtrace, näemme, että olimme toiminto oh_no,
joka kutsui toimintoa dinky, joka kutsuttiin toiminto binky,
joka kutsui tärkeimmät.
Voimme myös nähdä argumentteja näitä toimintoja.
Argumentti dinky ja binky oli 1.
Jos me luettelo toiminnon oh_no, näemme, että oh_no on juuri tekemässä char ** s = NULL;
* S = "BOOM";
Miksi se epäonnistui?
[Opiskelija] Et voi dereference nollaosoittimen? >> Joo.
Tämä on vain sanomalla s on NULL, riippumatta jos se sattuu olemaan char **,
joka, riippuen siitä, miten tulkita se, se voisi olla osoitin osoittimen merkkijonon
tai joukko merkkijonoja.
Se s on NULL, niin * s on dereferencing nollaosoittimen,
joten tämä tulee kaatumaan.
Tämä on yksi nopeimmista tavoista voit mahdollisesti segfault.
Se on vain julistaa nollaosoittimen ja heti segfaulting.
Sitähän oh_no tekee.
Jos menemme ylös yhden ruudun, niin aiomme päästä toiminto nimeltään oh_no.
Minun täytyy tehdä se alas.
Jos et anna komento ja juuri Enteriä uudelleen,
se vain toistaa edellisen komennon että juoksi.
Olemme runko 1.
Listing tämä kehys, näemme tässä on meidän tehtävämme.
Voit lyödä listasta, tai voit tehdä listan 20 ja se lista enemmän.
Toiminto Dinky sanoo jos i on 1, siirry oh_no toiminto,
muuten siirry slinky toiminto.
Ja me tiedämme i on 1, koska satumme näkemään täällä
että Dinky kutsuttiin argumentti 1.
Tai voit vain tehdä tulostaa minä ja se sanoo i on 1.
Olemme parhaillaan dinky, ja jos menemme ylös toiseen kehykseen, tiedämme päädyt binky.
Up. Nyt olemme binky.
Listing tämä toiminto - luettelon ennen puoli keskeytti minut -
Se alkoi ikään kuin i on 0, niin me aiomme kutsua sitä oh_no, muuten soita dinky.
Tiedämme olin 1, niin sitä kutsutaan dinky.
Ja nyt olemme taas tärkein, ja tärkeimmät on vain olemaan int i = rand ()% 3;
Tämä on juuri menossa antaa sinulle satunnaisluku joka on joko 0, 1 tai 2.
Se tulee soittaa binky tuon numeron, ja se palaa 0.
Tarkasteltaessa tätä,
vain kävelemällä ohjelman manuaalisesti suorittamatta sitä välittömästi,
voisitte asettaa taitekohta on tärkein, mikä tarkoittaa, että kun otamme ohjelmaan
ohjelma toimii kunnes se osuu taitekohta.
Joten käynnissä ohjelma, se kestää ja sitten se osuu päätehtävä ja lakkaa toimimasta.
Nyt olemme sisällä tärkein, ja askel tai vieressä aikoo tuoda meidät seuraavalle koodirivin.
Voit tehdä askel tai seuraava.
Lyömällä seuraavaksi, nyt on asetettu rand ()% 3, jotta voimme tulostaa arvon I
ja se sanoo i on 1.
Nyt sillä on väliä, onko käytämme seuraavaan tai vaiheeseen.
Kai se väliä edellisessä, mutta emme haluaisi käyttää seuraavaksi.
Jos käytämme vaiheessa, astumme toiminto, mikä tarkoittaa katsomaan todellinen asia
että tapahtuu sisällä binky.
Jos käytämme seuraavaan, se tarkoittaa, mennä yli toiminnon
ja vain siirtyä seuraavaan koodirivi meidän päätehtävä.
Täällä tällä linjalla, olin missä se sanoi rand ()% 3;
jos tein askel, se mennä täytäntöönpanoa randia
ja katsoa mitä siellä tapahtuu, ja voisin selata randia toimintoa.
Mutta en välitä randia toimintoa.
Haluan vain mennä seuraavaan koodirivin main, joten käytän seuraavaksi.
Mutta nyt en välitä binky toiminto, joten haluan astua siihen.
Nyt olen binky.
Ensimmäinen rivi koodia aikoo sanoa, jos (i == 0), otan askeleen,
näemme päädymme klo dinky.
Jos me lista asioita, huomaamme, että se tarkistaa on i = 0.
i ei ole yhtä suuri kuin 0, niin se meni muuta kunnossa,
, joka on menossa soittaa dinky (i).
Saatat hämmentyä.
Jos katsokaa näitä rivejä suoraan, saatat ajatella, jos (i == 0),
Okei, sitten otin askeleen ja nyt olen dinky (i),
saatat ajatella, että täytyy tarkoittaa i = 0 tai jotain.
Ei, se vain tarkoittaa, että se tietää sen voi tarttua suoraan linjan dinky (i).
Koska en ole 0, seuraava vaihe ei tule päättyä muuta.
Else ei linjaa se tulee pysähtyä.
Se on vain menossa seuraavalle riville se voi todella toteuttaa, mikä on sievä (i).
Astumassa dinky (i), näemme, jos (i == 1).
Tiedämme i = 1, joten kun astumme, me tiedämme aiomme päätyä oh_no
koska i = 1 kutsuu funktiota oh_no, jossa voit astua,
joka aikoo perustaa char ** s = NULL ja heti "BOOM".
Ja sitten itse katsot täytäntöönpanon buggy2,
Tässä, i on vain saada satunnaisluvun - 0, 1, tai 2 - kutsuvan binky,
jotka, jos i on 0 se kutsuu oh_no, muuten se kutsuu dinky, joka tulee tänne.
Jos i on 1, puhelu oh_no, muuten soita piukka, jotka tulevat tänne,
jos i on 2, soita oh_no.
En edes usko, että on keino -
Onko kukaan katso tapa tehdä tämä ohjelma ei segfault?
Koska jos olen puuttuu jotain, jos i on 0, voit heti segfault,
muuten menet toiminto, joka jos i on 1 teitä segfault,
muuten menet toiminto, jossa jos i on 2 sinua segfault.
Joten ei ole väliä mitä teet, sinä segfault.
>> Luulen yksi tapa vahvistaa se olisi sen sijaan tehdä char ** s = NULL,
voisit malloc tilaa merkkijonon.
Voisimme tehdä malloc (sizeof) - sizeof mitä?
[Opiskelija] (char) * 5? >> Onko tämä tunnu oikealta?
Oletan tämä toimi, jos olen itse juoksi sen, mutta se ei ole mitä etsin.
Katsokaa tyyppi s. Katsotaanpa lisätä int *, joten int * x.
Tekisin malloc (sizeof (int)).
Tai jos halusin joukko 5, tekisin (sizeof (int) * 5);
Mitä jos minulla on int **?
Mitä minä malloc?
[Opiskelija] koko osoittimen. >> Joo. (Sizeof (int *));
Sama juttu täällä.
Haluan (sizeof (char *));
Tämä tulee jakaa tilan osoitin, joka viittaa "Boom".
Minun ei tarvitse varata tilaa "BOOM" itse
koska tämä on periaatteessa vastaa mitä sanoin aiemmin
nieriää * x = "BOOM".
"BOOM" on jo olemassa. Se tapahtuu olemassa vain luku-alue muistia.
Mutta se on jo olemassa, joten tämä rivi koodia, jos s on char **,
sitten * s on char * ja olet luomassa tätä char * viitata "BOOM".
Jos halusin kopioida "BOOM" osaksi s, niin olisin tarvitse varata tilaa s.
Teen * s = malloc (sizeof (char) * 5);
Miksi 5?
Miksei 4? Se näyttää "BOOM" on 4 merkkiä. >> [Opiskelija] nollamerkki.
Joo. Kaikki jouset ovat menossa nollamerkki.
Nyt voin tehdä jotain strcat - Mikä on funktio kopioitaessa merkkijono?
[Opiskelija] CPY? >> Strcpy.
mies strcpy.
Joten strcpy tai strncpy.
strncpy on vähän turvallisempi, koska voit määrittää tarkasti, kuinka monta merkkiä,
mutta täällä sillä ei ole väliä, koska me tiedämme.
Joten strcpy ja katsoa väitteitä.
Ensimmäinen argumentti on päämäärämme.
Toinen perustelu on meidän lähde.
Aiomme kopioida päämääräämme * S osoitin "BOOM".
Miksi ehkä haluat tehdä tämän strcpy eikä vain mitä meillä oli ennen
ja * s = "BOOM"?
On syytä saatat haluta tehdä tämän, mutta mikä on se syy?
[Opiskelija] Jos haluat muuttaa jotain "BOOM". >> Joo.
Nyt voin tehdä jotain s [0] = 'X';
koska s pistettä kasaan ja tilaa kasa että s on osoittaa
on osoitin enemmän tilaa kasaan, joka tallennetaan "Boom".
Joten tämä kopio "BOOM" on tallennettu kasaan.
On teknisesti kaksi kappaletta "BOOM" meidän ohjelmaan.
On ensimmäinen, joka on juuri antanut tämän "BOOM" string vakio,
ja toinen kopio "BOOM", strcpy luotu kopio "BOOM".
Mutta kopio "BOOM" on tallennettu kasaan, ja kasan olet vapaa muuttamaan.
Keko ei ole vain luku-, niin se tarkoittaa, että s [0]
tulee voit muuttaa arvoa "BOOM".
Se tulee voit muuttaa näitä merkkejä.
>> Kysymyksiä?
Okei.
>> Siirryn buggy3, katsotaanpa gdb buggy3.
Me vain käyttää sitä ja näemme saamme segfault.
Jos me backtrace, on olemassa vain kaksi tehtävää.
Jos menemme ylös meidän päätehtävä, huomaamme, että me segfaulted tällä rivillä.
Joten vain katsomalla tätä linjaa, for (int rivi = 0; fgets tätä kamaa ei ole yhtä NULL;
line + +).
Meidän edellinen kuva kutsuttiin _IO_fgets.
Huomaat, että paljon sisäänrakennettu C funktioiden
että kun saat segfault, siellä on todella arvoituksellinen funktioiden nimet
näin _IO_fgets.
Mutta se tulee suhteuttaa tähän fgets puhelun.
Jossain sisällä täällä, olemme segfaulting.
Jos katsomme argumentteja fgets, voimme tulostaa puskuriin.
Katsotaanpa tulostaa - Voi ei.
Tulosta ei tule toimimaan juuri niin kuin haluan sen.
Katsokaamme varsinaisen ohjelman.
Buffer on merkki array. Se on luonteeltaan joukko 128 merkkiä.
Joten kun sanon tulostuspuskurissa, se tulee tulostaa ne 128 merkkiä,
mikä kai on mitä odotetaan.
Mitä olin etsimässä on tulostaa osoite puskuri,
mutta se ei oikeastaan ​​kerro paljon.
Joten kun Satun sanoa täällä x puskuri, se osoittaa minulle 0xbffff090,
joka, jos muistat aiemmista tai jossain vaiheessa, Oxbffff yleensä pino-ish alueella.
Pino taipumus aloittaa jostain hieman alle 0xc000.
Vain katsomalla tätä osoitetta, tiedän että puskuri tapahtuu pinon.
Uudelleenkäynnistys minun ohjelma, ajaa, ylös, puskuri näimme oli tämä merkkijono
jotka ovat melko merkityksettömiä.
Sitten tulostus tiedostoon, mitä tiedosto näyttää?
[Opiskelija] Null. >> Joo.
Tiedosto on tyyppiä FILE *, joten se on osoitin,
ja arvo, että osoitin on nolla.
Joten fgets aikoo yrittää lukea, että osoitin epäsuorasti,
mutta päästäkseen että osoitin, se on dereference sitä.
Tai, voidakseen käyttää mitä sen pitäisi osoittaa, se dereferences sitä.
Joten se dereferencing nollaosoittimen ja sen segfaults.
Olisin voinut uudelleen sinne.
Jos rikomme meidän tärkein asia ja ajaa,
ensimmäinen rivi koodia on char * filename = "nonexistent.txt";
Tämän pitäisi antaa aika iso vihje siitä, miksi tämä ohjelma epäonnistuu.
Kirjoittamalla vieressä pääsen seuraavalle riville, jos avaan tämän tiedoston,
ja sitten heti päästä meidän linja, jossa kerran osuin Seuraavaksi tulee segfault.
Haluaako joku heittää ulos miksi emme voisi segfaulting?
[Opiskelija] Tiedostoa ei löydy. >> Joo.
Tämä on tarkoitus olla vihje
että kun avaat tiedoston sinun tarkistaa, että tiedosto olemassa.
Joten tässä, "nonexistent.txt";
Kun me fopen tiedostonimi käsittelyssä meillä sitten on sanottava
if (tiedosto == NULL) ja sano printf ("Tiedostoa ei ole olemassa!"
tai - vielä parempaa - filename), paluu 1;
Joten nyt tarkistaa, jos se on NULL
ennen itse jatkaa ja yrittää lukea tiedoston.
Voimme sen uudestaan ​​vain nähdä, että toimii.
Aioin sisällyttää uusi rivi.
Joten nyt nonexistent.txt ei ole olemassa.
Sinun tulisi aina tarkistaa tällaista asiaa.
Sinun tulisi aina tarkistaa, jos fopen palauttaa NULL.
Sinun tulisi aina varmista, että malloc ei palauta NULL,
tai muuten segfault.
>> Nyt buggy4.c.
Running. Olen arvaamaan tätä odottaa syötteitä tai mahdollisesti ääretön silmukka.
Kyllä, se on ääretön silmukka.
Niin buggy4. Näyttää siltä, ​​että olemme äärettömän looping.
Voimme murtaa tärkeimmissä, ajaa meidän ohjelma.
In gdb, niin kauan kuin lyhenne käytät on yksiselitteinen
tai erityisiä lyhenteitä että ne tarjoavat sinulle,
voit käyttää n käyttöön seuraavan sijaan tarvitse kirjoittaa ulos ensi aina.
Ja nyt kun olen lyönyt n kerran, voin vain Enter pitää käynnissä seuraavaksi
sen sijaan, että osuma n Anna, N Anna, n Anna.
Näyttää siltä, ​​että olen jonkinlaisessa varten silmukka, joka on asetus array [i] ja 0.
Se näyttää olen koskaan murtaa pois tämä silmukka.
Jos minä tulostaa i, niin i on 2, sitten menen seuraavaksi.
Minä tulostaa i, i on 3, sitten menen seuraavaksi.
Minä tulostaa i ja i on 3. Seuraavaksi, tulostaa i, i on 4.
Oikeastaan ​​tulosta sizeof (array), joten koko joukko on 20.
Mutta näyttää siltä, ​​että joitakin erityisiä gdb komento menee kunnes jotain tapahtuu.
Se on kuin asettamalla ehdon muuttujan arvo. Mutta en muista mitä se on.
Joten jos pidämme menossa -
Mitä sanoit? Mitä toit esille?
[Opiskelija] Onko näkyviin voin lisätä - >> Joo. Joten näyttää voin auttaa.
Jos me vain näyttää i, se laittaa tänne mitä arvo I on
joten minun ei tarvitse tulostaa sen joka kerta.
Jos me vain pitää käynnissä seuraavan, näemme 0, 1, 2, 3, 4, 5, 0, 1, 2, 3, 4, 5, 0, 1, 2, 3, 4, 5.
Jotain menee pahasti pieleen, ja minä ollaan palauttaa 0.
Tarkasteltaessa buggy4.c, näemme kaikki tapahtuu on int array [5];
for (i = 0; i <= sizeof (array); i + +)
array [i] = 0;
Mitä me näemme, että on väärin täällä?
Kuten vihje, kun olin tekemässä gdb buggy4 - Katsotaanpa murtaa tärkein, run -
En print sizeof (array) vain nähdä, mitä tila on, jos minun pitäisi viimein puhkeaa.
Missä olen? Juoksinko?
En julistaa vielä.
Joten tulostaa sizeof (array) ja se on 20,
joka on odotettavissa, koska minun joukko on kooltaan 5 ja se on 5 kokonaislukuja,
niin koko juttu olisi 5 * sizeof (int) tavua, missä sizeof (int) on yleensä 4.
Joten sizeof (array) on 20.
Mitä pitäisi olla?
[Opiskelija] jaettuna sizeof (int). >> Joo, / sizeof (int).
Näyttää siltä, ​​että on vielä ongelma. Minusta tämän pitäisi olla vain <
koska se on oikeastaan ​​aina <ja koskaan <=.
Nyt miettiä miksi tämä oli todella rikki.
Onko kellään arvauksia miksi olin palauttaa 0 läpi kunkin iterointia silmukan?
Ainoa asia sisällä täällä, että tapahtuu on että taulukko [i] on asetettu 0.
Eli jotenkin tämä rivi koodia aiheuttaa meidän int i voidaan asettaa 0.
[Opiskelija] Voisiko olla, koska se on pakottava muisti tämän osan I
kun se luulee sen seuraavaan elementtiin array? >> [Bowden] Kyllä.
Kun menemme pidemmälle loppua meidän array,
jotenkin, että tilaa että olemme pakottavilla on ohittaa arvon i.
Ja niin jos katsomme buggy4, rikkoa tärkein, run,
Katsotaanpa tulostaa osoite i.
Se näyttää se bffff124.
Nyt tulostaa osoite array [0]. 110.
Entä [1]? 114.
[2], 118.
11c, 120. array [5] on bfff124.
Joten array [5] on sama osoite kuin minä, mikä tarkoittaa sitä, että ryhmä [5] on i.
Jos niillä on sama osoite, niin ne ovat sama asia.
Joten kun asetamme array [5] 0, asetamme i 0.
Ja jos ajattelee tämän suhteen pinon,
int i julistetaan ensin, mikä tarkoittaa minä saa vähän tilaa pinoon.
Sitten array [5] on varattu, niin sitten 20 tavua jaetaan pinoon.
Joten minä saa kohdistetaan ensin, sitten nämä 20 tavua saada jaettu.
Joten olen tapahtuu juuri ennen array,
ja sillä tavalla, niin kuin sanoin viime viikolla, kun se on teknisesti pino kasvaa alaspäin,
kun indeksinä array, me taataan, että 0. asema array
tapahtuu aina ennen ensimmäistä asemaa array.
Tämä on tavallaan kuinka piirsin sen viime viikolla.
Huomaa, että alareunassa meillä on osoite 0 ja yläreunassa meillä osoitetta Max.
Pino kasvaa jatkuvasti alaspäin.
Sanotaan kohdentaa i.
Me jakaa kokonaisluku i, joka tarkoittaa Sanotaan vain tänne kokonaisluku i saa myönnetty.
Sitten me jakaa myös joukko 5 kokonaislukuja, mikä tarkoittaa, että alla, että
koska pino kasvaa alaspäin, ne 5 kokonaislukuja saada jaettu.
Mutta koska kuinka paneelit toimi, olemme taattu, että ensimmäinen asema array
aina osoitteen pienempi kuin toinen asia array.
Joten array asentoon 0 on aina tapahtua ensin muistiin,
taas array asento 1 on tapahduttava jälkeen
ja array asema 2 on tapahtua sen jälkeen,
mikä tarkoittaa, että joukko asennossa 0 tapahtuisi jossain täällä,
array asennossa 1 kävisi yläpuolella
koska liikkeestä tarkoittaa korkeampia osoitteita, koska suurin osoite on täällä.
Joten array [0] tänne, array [1] täällä, array [2] täällä, array [3] täällä.
Huomaa miten ennen me jaetaan kokonaisluku i aina tänne,
kun siirrymme pidemmälle ja syvemmälle meidän array olemme pääsemässä lähemmäs ja lähemmäs kokonaisluku i.
Se vain on niin, että array [5], joka on yksi paikka riistäytynyt array,
on tarkalleen missä kokonaisluku satuin jaetaan.
Niin, että piste missä satumme lyödä tilaa pinoon
että oli varattu kokonaisluku i, ja olemme asettaa se, 0.
>> Näin se toimii. Kysymyksiä? Joo.
[Opiskelija] Älä välitä. Okei.
[Opiskelija] Miten välttää näitä tavallaan virheitä?
Nämä tavallaan virheitä? Älä käytä C ohjelmointikieli.
Käytä kieltä, joka on indeksirajojen tarkistamista.
Niin kauan kuin olet varovainen, sinun tarvitsee vain välttää menossa ohi rajat teidän array.
[Opiskelija] Joten tässä kun menimme ohi rajat teidän array -
[Bowden] Siinä missä asiat alkavat mennä pieleen. >> [Opiskelija] Ai, okei.
Niin kauan kuin pysyt varattu muisti oman array, olet hieno.
Mutta C ei ole Virheentarkistus. Jos en array [1000], se mielellään vain muuttaa mitä tapahtuu -
Se menee alussa array, sitten se menee 1000 kannat jälkeen ja asettaa sen 0.
Se ei tee mitään tarkastaminen, että oi, tämä ei oikeastaan ​​ole 1000 asioita siinä.
1000 on paljon suurempi kuin minun pitäisi muuttaa,
taas Java tai jotain saat joukko out of bounds indeksin
tai indeksin out of bounds poikkeus.
Siksi paljon korkeamman tason kielillä on näitä asioita
jos jos ylittää rajoja array, ette
joten et voi muuttaa asioita alta sinua
ja sitten asiat menevät paljon pahempi kuin vain saada poikkeus
sanomalla että menit päättymisen jälkeen jono.
[Opiskelija] Ja niin meidän pitäisi olla juuri muuttuneet <= vain <? >> [Bowden] Joo.
Sen pitäisi olla <sizeof (array) / sizeof (int);
koska sizeof (array) on 20, mutta me vain haluamme 5. >> [Opiskelija] Oikea.
Lisää kysymyksiä? Okei.
>> [Opiskelija] Minulla on kysymys. >> Joo.
[Opiskelija] Mikä on todellinen taulukkomuuttujaan?
[Bowden] Kuten mitä on array?
Array itsessään on symboli.
Se on vain osoite alusta 20 tavua, että olemme viitataan.
Voit ajatella sitä osoitin, mutta se on vakio osoitin.
Heti asiat saavat koottu, muuttuja array ei ole enää.
[Opiskelija] Joten miten se löytää kokoa array?
Koko array viittaa kokoon, että lohko, että symboli viittaa.
Kun teen jotain printf ("% p \ n", array);
Katsotaanpa käyttää sitä.
Mitä minä juuri teen väärin?
Array "array" ilmoitetaan tässä.
Voi, täällä.
Clang on älykäs, ja se sattuu huomaan julisti levyjärjestelmän 5 elementtiä
mutta olen indeksointi paikoilleen 1000.
Se voi tehdä niin, koska nämä ovat vain vakioita.
Se voi vain mennä niin pitkälle huomaamatta, että aion ylittää rajat array.
Mutta huomaa ennen kun olimme minä olla virheellisiä,
se ei voi päättää, kuinka monta arvot voisin ottaa,
joten se ei voi määritellä, että olin menossa pään yli array.
Se on vain clang olla fiksu.
>> Mutta nyt tehdä buggy4. Joten mitä muuta teen väärin?
Epäsuorasti todetaan kirjaston funktion 'printf'.
Aion haluta # include .
Okei. Nyt käynnissä buggy4.
Tulostaminen arvo array kuten tein täällä, tulostaa sen osoitin
tulosteita jotain, joka näyttää tältä - bfb8805c - mikä on jonkin verran osoite
se on pinossa-ish alueella.
Array itsessään on kuin osoitin, mutta se ei ole todellinen osoitin,
koska säännöllinen osoittimen voimme muuttua.
Array on vain joitakin vakio. 20 lohkot muistin alkavat osoitteesta 0xbfb8805c.
Joten bfb8805c tällä osoite +20--tai kai -20 -
on kaikki varattu muisti tämän taulukon.
Array, muuttuja itsessään ei ole tallennettu minnekään.
Kun olet laadinnassa, kääntäjä - käsi aalto sitä -
mutta kääntäjä vain käyttää se tietää array olla.
Se tietää missä se array alkaa,
ja niin se voi aina vain tehdä asioita suhteen vastikkeiden tuosta alusta.
Se ei tarvitse muuttuja itse edustaa array.
Mutta kun teen jotain int * p = array; nyt p on osoitin, joka osoittaa, että jono,
ja nyt p todella on olemassa pinoon.
Olen vapaa muuttamaan s.. Voin tehdä p = malloc.
Joten se alunperin huomautti array, nyt se osoittaa jonkin verran tilaa kasaan.
En voi tehdä array = malloc.
Jos clang on fiksu, se huutaa minulle oikeus pois bat.
Oikeastaan, olen melko varma, gcc tekisi tämäkin.
Joten array type "int [5] ei ole siirrettävissä.
Et voi määrittää jotain array tyyppiä
koska matriisi on vakio.
Se on symboli mitkä nuo 20 tavua. En voi muuttaa sitä.
>> [Opiskelija] Ja jos on taulukon koko säilytetään?
[Bowden] Se ei tallenneta mihinkään. Se kun se kootaan.
Eli jos on kokoa array säilytetään?
Voit käyttää sizeof (array) sisällä toiminto matriisi on julistautunut.
Joten jos teen jonkin toiminnon, foo, ja minä (int array [])
printf ("% d \ n", sizeof (array));
ja sitten täällä Kutsun foo (array);
sisällä tätä toimintoa - Katsotaanpa käyttää sitä.
Tämä on clang olla fiksu uudelleen.
Se kertoo minulle, että sizeof on array funktio parametrin
palaa koko 'int *'.
Tämä olisi virhe, jos se ei ole mitä halusin tapahtua.
Katsotaan todellakin sammuu Werror.
Varoitus. Varoitukset ovat hienoja.
Se on edelleen kääntää niin kauan kuin se on varoitus.
. / A.out tulee tulostaa 4.
Varoitus, että syntyi on selkeä osoitus siitä, mikä meni pieleen.
Tämä int array on juuri menossa painoon sizeof (int *).
Vaikka laitan array [5] täällä, se on silti vain painoon sizeof (int *).
Joten heti kun siihen johdetaan toiminto, ero taulukot ja osoittimet
on olematon.
Tämä sattuu olemaan joukko, joka oli ilmoitettu pinoon,
mutta heti kun kuljemme tätä arvoa, että 0xbf blaa, blaa, blaa tähän toiminto,
sitten tämä osoitin osoittaa, että array pinoon.
Joten se tarkoittaa, että sizeof sovelletaan vain toiminto, joka array julistettiin,
mikä tarkoittaa, että kun olet laadinnassa tätä toimintoa,
kun clang kulkee tätä toimintoa, se näkee array on int joukko koko 5.
Joten se näkee sizeof (array). No, se on 20.
Se on oikeastaan ​​miten sizeof periaatteessa toimii lähes kaikissa tapauksissa.
Sizeof ei funktio, se operaattori.
Et soita sizeof toiminto.
Sizeof (int), kääntäjä vain kääntää että 4.
Ymmärsitkö? Okei.
>> [Opiskelija] Mitä eroa on sizeof (array) pää-ja foo?
Tämä johtuu siitä, että me sanomme sizeof (array), joka on tyyppiä int *,
taas array täällä ei ole tyyppiä int *, se int array.
>> [Opiskelija] Joten jos sinulla on ollut parametri array [] sijasta int * array,
se tarkoittaisi, että voisit vielä muuttaa array koska nyt se osoitin?
[Bowden] Pidätkö tästä? >> [Opiskelija] Joo. Voitko muuttaa array sisällä toiminto nyt?
[Bowden] Voisit muuttaa array molemmissa tapauksissa.
Molemmissa tapauksissa on ilmaiseksi sanoa array [4] = 0.
[Opiskelija] Mutta voit tehdä erilaisia ​​valitse jotain muuta?
[Bowden] Oh. Joo. Kummassakin tapauksessa - >> [opiskelija] Joo.
[Bowden] ero array [] ja int * taulukko, ei kukaan.
Voit myös saada joitakin moniulotteinen array täällä
joillekin kätevä syntaksi, mutta se on silti vain osoitin.
Tämä tarkoittaa sitä, että olen vapaa tekemään array = malloc (sizeof (int)); ja nyt kohta jossain muualla.
Mutta aivan kuten miten tämä toimii ikuisesti ja aina,
muuttamalla array tekemällä osoitat jotain muuta
ei muuta tätä array tänne, koska se on kopio väitteen,
se ei ole osoitin kyseiseen väitteeseen.
Ja itse asiassa, kuten enemmän viitteitä siitä, että se on täsmälleen sama -
me jo näki mitä tulostus array tulosteita -
mitä jos me tulostaa osoite matriisissa tai osoite osoite array
jompaankumpaan?
Katsotaanpa sivuuttaa tätä.
Okei. Tämä on hieno. Se on nyt käynnissä. / A.out.
Tulostus array sitten tulostaa osoite array, ovat sama asia.
Array vain ei ole olemassa.
Se tietää, milloin olet tulostat array, olet tulostat symboli, joka viittaa niihin 20 tavua.
Tulostaminen osoite array, hyvin, array ei ole olemassa.
Se ei ole osoitetta, niin se vain tulostaa osoite näiden 20 tavua.
Heti kun kääntää alas, kuten teidän koottu buggy4. / A.out,
array on olematon.
Pointers olemassa. Arrays ei.
Lohkojen muistia edustavat array edelleen olemassa,
mutta vaihteleva joukko, ja muuttujat, jotka tyyppiä ei ole olemassa.
Ne ovat kuin tärkeimmät erot taulukot ja osoittimet
ovat heti teet funktiokutsut, ei ole mitään eroa.
Mutta sisällä toiminto itse taulukon julistetaan, sizeof toimii eri
koska olet tulostaa niiden lohkojen koon sijasta koko tyyppiä,
ja et voi muuttaa sitä, koska se on merkki.
Tulostaminen asia ja osoitteen asia tulostuu sama asia.
Ja se on aika paljon se.
[Opiskelija] Voisitko sanoa, että vielä kerran?
Olisin jäänyt jotain.
Tulostus valikoima ja osoite array tulostaa sama asia,
taas jos tulostat osoittimen vs. osoite osoitin,
yksi asia tulostaa osoite mitä olet osoittaa,
muut tulostaa osoitteen osoittimen pinoon.
Voit muuttaa osoittimen, et voi muuttaa taulukon symboli.
Ja sizeof osoitin tulee tulostaa koko tuon osoittimen tyyppiä.
Joten int * p sizeof (p) on menossa painoon 4,
mutta int array [5] print sizeof (taulukko) on menossa painoon 20.
[Opiskelija] Joten int array [5] tulostaa 20? >> Kyllä.
Siksi sisälle buggy4 kun se käytti olla sizeof (taulukko)
tämä oli tekemässä i <20, joka ei ole sitä mitä halusimme.
Haluamme i <5. >> [Opiskelija] Okei.
[Bowden] Ja sitten heti aloittaa kulkevat toiminnot,
jos teimme int * p = array;
sisällä tätä toimintoa, voimme periaatteessa käyttää p ja array täsmälleen samalla tavalla,
lukuun ottamatta sizeof ongelma ja muuttuviin ongelma.
Mutta p [0] = 1, on sama kuin sanoa array [0] = 1;
Ja heti kun sanomme foo (array) tai foo (p);
sisällä foo-toiminto, tämä on sama puhelu kahdesti.
Ei ole mitään eroa näiden kahden puhelun.
>> Jokainen hyvä siitä? Okei.
Meillä on 10 minuuttia.
>> Yritämme päästä läpi Hacker Typer ohjelmaa,
Tässä sivusto, joka tuli ulos viime vuonna tai jotain.
Se vain pitäisi olla kuin kirjoitat satunnaisesti ja se tulostaa -
Mitä tahansa tiedoston sattuu ladannut on sitä miltä näyttää kirjoitat.
Se näyttää jonkinlainen käyttöjärjestelmän koodia.
Sitähän me haluamme toteuttaa.
Sinun pitäisi olla suoritettavassa nimeltä hacker_typer
joka vie yhteen väitteeseen, tiedosto "hakkeri tyyppi."
Running suoritettavan pitäisi tyhjentää näytön
ja sitten tulostaa yhden merkin läpikulkevien-tiedostojen aina käyttäjä painaa näppäintä.
Joten mitä näppäintä painat, sen pitäisi heittää pois, ja sen sijaan tulostaa hahmo tiedosto
että on argumentti.
Minä melko paljon kertoa teille, mitä asioita aiomme pitää tietää ovat.
Mutta haluamme tarkistaa termios kirjastoon.
En ole koskaan käyttänyt tätä kirjastoa koko elämässäni, joten se on hyvin minimaalinen tarkoituksiin.
Mutta tämä tulee olemaan kirjastoon voimme heittää pois merkki osut
Kun kirjoitat osaksi standardia sisään
Joten hacker_typer.c, ja aiomme haluavat # include .
Tarkasteltaessa man-sivulla termios - Olen arvaamaan se päätteelle OS tai jotain -
En osaa lukea sitä.
Tarkasteltaessa tätä, se sanoo sisällyttää näihin 2 tiedostoa, joten teemme sen.
>> Ensimmäinen asia ensin haluamme toteuttaa yhtenä perustelu, joka on tiedosto pitäisi avata.
Joten mitä haluan tehdä? Miten tarkistaa, minulla on yksi argumentti?
[Opiskelija] Jos argc vastaa sitä. >> [Bowden] Joo.
Joten jos (argc! = 2) printf ("Käyttö:% s [Avaa tiedosto]").
Joten nyt jos ajaa tämä ilman että toinen väite - oh, tarvitsen uuden linjan -
näet sanotaan Käyttö:. / hacker_typer,
ja sitten toinen argumentti olisi tiedosto Haluan avata.
Nyt mitä teen?
Haluan lukea tämän tiedoston. Miten lukea tiedostoa?
[Opiskelija] Avaat sen ensin. >> Joo.
Niin fopen. Mitä fopen näyttää?
[Opiskelija] Tiedostonimi. >> [Bowden] Tiedoston tulee olemaan argv [1].
[Opiskelija] Ja sitten mitä haluat tehdä sen kanssa, joten - >> [Bowden] Joo.
Joten jos et muista, voit vain tehdä mies fopen,
jossa se tulee olemaan const char * polku missä polku on tiedostonimi,
const char * mode.
Jos satut muistaa missä tilassa on, voit etsiä tilaan.
Sisällä ihmisen sivuja, kauttaviiva merkki on mitä voit etsiä asioita.
Joten kirjoitan / tila etsiä tilaan.
n ja N ovat mitä voit selata haku otteluissa.
Täällä sanotaan väitteen tila osoittaa merkkijono
alkaen yksi seuraavista sekvensseistä.
Joten R, avaa tekstitiedosto lukemista varten. Sitähän me haluamme tehdä.
Lukemiseen, ja haluan säilyttää se.
Asia tulee olemaan FILE *. Nyt mitä haluan tehdä?
Anna minulle toinen.
Okei. Nyt mitä haluan tehdä?
[Opiskelija] Tarkista se NULL. >> [Bowden] Joo.
Aina kun avaat tiedoston, varmista, että olet onnistuneesti pystyä avaamaan sitä.
>> Nyt haluan tehdä termios juttuja missä haluan ensin lukea minun nykyiset asetukset
ja tallenna ne johonkin, niin haluan muuttaa asetuksia
heittää pois mitä tahansa merkkiä, joka kirjoitan,
ja sitten haluaisin päivittää näitä asetuksia.
Ja sitten lopussa ohjelman, haluan vaihtaa takaisin alkuperäiseen asetukset.
Joten struct tulee olemaan tyyppiä termios, ja aion haluavat kaksi näistä.
Ensimmäinen tulee olemaan minun current_settings,
ja sitten he tulevat olemaan minun hacker_settings.
Ensiksi aion haluat tallentaa minun nykyiset asetukset,
Sitten aion haluat päivittää hacker_settings,
ja sitten miten lopussa minun, haluan palata nykyiset asetukset.
Joten säästää nykyiset asetukset, niin että toimii, meillä mies termios.
Näemme, että meillä on tämä int tcsetattr, int tcgetattr.
Minä kulkea termios struct sen osoitin.
Miten tämä näyttää on - I've jo unohtaneet mitä toimintoa kutsuttiin.
Kopioi ja liitä se.
Joten tcgetattr, niin haluan kulkea struct että olen säästö tietoa,
joka tulee olemaan current_settings,
ja ensimmäinen argumentti on tiedosto kuvaaja asia, jonka haluan tallentaa ominaisuuksia.
Mikä tiedosto avainsana on on kuin aina, kun avaat tiedoston, se saa tiedoston avainsana.
Kun minä fopen argv [1], se saa tiedoston avainsana johon viittaat
kun haluat lukea tai kirjoittaa sitä.
Se ei ole tiedoston avainsana haluan käyttää täällä.
On kolme tiedostoa kuvaajat olet oletuksena,
jotka ovat vakiona, vakio ulos, ja keskivirhe.
Oletuksena mielestäni se on standardi on 0, standardi out on 1, ja keskivirhe on 2.
Joten mitä haluan muuttaa asetuksia?
Haluan muuttaa asetuksia kun osuin luonne,
Haluan sen heittää, että merkki pois sen sijaan tulostaa sen näytölle.
Mitä stream - standardi, standardi ulos tai keskivirhe -
reagoi asioihin kun kirjoitan at näppäimistöä? >> [Opiskelija] Standard sisään >> Joo.
Joten en voi joko tehdä 0 tai voin tehdä stdin.
Saan current_settings standardin tuumaa
>> Nyt haluan päivittää näitä asetuksia,
joten ensin minä kopioida hacker_settings mitä minun current_settings ovat.
Ja kuinka tietueet työ on se vain kopioi.
Tämä kopioi kaikki kentät, kuten odottaa.
>> Nyt haluan päivittää joitakin kenttiä.
Looking at termios, sinun pitäisi lukea läpi paljon tämän
vain nähdä mitä haluaisi etsiä,
mutta liput aiot halua etsiä ovat kaiku,
joten Echo Echo syötetyt merkit.
Ensin haluan asettaa - I've jo unohtaneet, mitä kentät ovat.
Tämä on mitä struct näyttää.
Joten tulotiloissa mielestäni me haluamme muuttaa.
Me tutustumme ratkaisu varmistaa, että se mitä me haluamme muuttaa.
Haluamme muuttaa lflag estämiseksi tarvitse käydä läpi kaikkia näitä.
Haluamme muuttaa paikallista tilaa.
Sinun olisi pitänyt lukea läpi tätä koko juttu ymmärtää missä kaikki kuuluu
että me haluamme muuttaa.
Mutta se on sisällä paikallisia liikennemuotojen minne olemme menossa halua muuttaa sitä.
Joten hacker_settings.cc_lmode on mikä sen nimi on.
c_lflag.
Tämä on, jos pääsemme bittioperaatioiden.
Olemme aika myöhään, mutta menemme läpi todella nopeasti.
Tästä me päästä bittioperaatioiden,
missä Luulen sanoi kerran kauan sitten, että kun aloitat tekemisissä liput,
aiot käyttää bittioperaattori paljon.
Jokainen bitti lipun vastaa jonkinlaista käyttäytymistä.
Joten tässä, tämä lippu on joukko erilaisia ​​asioita, jossa ne kaikki tarkoittaa jotain erilaista.
Mutta mitä haluan tehdä, on vain sammuttaa bitin joka vastaa ECHO.
Niin kääntää että pois en & = ¬ ECHO.
Oikeastaan, mielestäni se on kuin techo tai jotain. Aion tarkistaa uudelleen.
Voin termios sen. Se on vain ECHO.
ECHO tulee olemaan yksi bitti.
¬ ECHO aikoo merkitä kaikki bitit asetetaan 1, mikä tarkoittaa kaikkia liput on asetettu true
lukuun ottamatta ECHO vähän.
Lopettamalla oman paikallisen lippuja tämän, se tarkoittaa kaikkia lippuja tällä hetkellä asetettu true
edelleen asetetaan totta.
Jos minun ECHO lippu on true, niin tämä on väistämättä asetettu FALSE ECHO lippua.
Joten tämä koodirivi vain sammuu ECHO lippua.
Muut riviä koodia, minä vain kopioida niitä edun ajan ja sitten selittää niitä.
Liuoksessa, hän sanoi 0.
Se on luultavasti parempi nimenomaan sanoa stdin.
>> Huomaa, että olen myös tekemässä ECHO | ICANON täällä.
ICANON viittaa jotain erillistä, mikä tarkoittaa kanoninen tilassa.
Mitä kanoninen tila tarkoittaa yleensä kun kirjoitat ulos komentoriviltä,
standardi ei käsittele mitään kunnes osut rivinvaihtoa.
Joten jos et GetString, kirjoitat joukko asioita, niin osut rivinvaihtoa.
Silloin se on lähetetty standardin tuumaa
Tuo oletus.
Kun suljen kanoninen tilassa, nyt jokainen merkki painat
on mitä saa käsitellä, joka on yleensä sellainen huono, koska se on hidas käsitellä näitä asioita,
minkä vuoksi se on hyvä puskuri sen koko riviä.
Mutta haluan jokaisen merkin voidaan käsitellä
koska en halua sitä odottaa minua lyödä rivinvaihto
ennen kuin se käsittelee kaikki merkit olen kirjoittamalla.
Tämä poistaa kanoninen tilassa.
Tämä kamaa vain tarkoittaa, kun se todellisuudessa käsittelee merkkiä.
Tämä tarkoittaa käsittelee ne välittömästi; pian kirjoittaessani heitä, käsitellä niitä.
Ja tämä on toiminto, joka päivittää minun asetukset vakiona,
ja TCSA keinot tehdä se nyt.
Muut vaihtoehdot ovat odottaa kaiken on parhaillaan prosessoidaan.
Se ei oikeastaan ​​väliä.
Juuri nyt muutan asetuksia on mitä on tällä hetkellä hacker_typer_settings.
Luulen sitä kutsui hacker_settings, joten katsotaanpa muuttaa.
Vaihda kaiken hacker_settings.
>> Nyt lopussa ohjelmamme aiomme haluat palauttaa
, mikä on tällä hetkellä sisällä normal_settings,
joka tulee vain näyttää & normal_settings.
Ilmoitus En ole muuttanut mitään minun normal_settings koska alunperin saada se.
Sitten vain muuttaa niitä takaisin, välitän ne takaisin lopussa.
Tämä oli päivitys. Okei.
>> Nyt sisällä täällä minä vain selittää koodi edun ajan.
Se ei ole paljon koodia.
Näemme luemme merkin tiedostosta. Kutsuimme sitä f..
Nyt voit ihminen fgetc, mutta miten fgetc menee töihin
on juuri se tulee palauttaa merkin, että olet juuri lukenut tai EOF,
joka vastaa tiedoston loppuun tai tapahtuu jokin virhe tapahtuu.
Olemme looping, edelleen lukea yhden merkin tiedostosta,
kunnes olemme loppuu merkkiä lukea.
Ja kun me teemme, että odotamme yhteen hahmo vakio tuumaa
Joka kerta kun kirjoitat jotain komentoriviltä,
että on lukemista hahmo vakio tuumaa
Sitten putchar on juuri menossa laittaa char luimme täällä tiedostosta standardin ulos.
Voit mies putchar, mutta se on vain laskemisesta standardin ulos, se tulostetaan, että merkki.
Voisit myös vain tehdä printf ("% c", c); Sama idea.
Se tulee tehdä suurin osa työstä.
>> Viimeinen asia aiomme haluavat tehdä vain FSulje meidän tiedoston.
Jos et FSulje, se muistivuoto.
Haluamme FSulje tiedosto olemme alunperin avattu, ja mielestäni se on siinä.
Jos teemme, että olen jo saanut ongelmia.
Katsotaanpa.
Mitä se valittaa?
Odotettu INT mutta väite on tyyppiä 'struct _IO_FILE * ".
Näemme jos se toimii.
Sallittu ainoastaan ​​C99. Augh. Okei, tee hacker_typer.
Nyt saamme enemmän hyötyä kuvauksia.
Joten käytä pimeää tunniste "normal_settings".
En kutsu sitä normal_settings. Kutsuin sitä current_settings.
Joten muuttaa kaikki tämä.
Nyt kulkee argumentti.
Teen tätä 0 nyt.
Okei. . / Hacker_typer cp.c.
En myöskään tyhjentää näytön alussa.
Mutta voit katsoa taaksepäin viime Harjoitus nähdä miten tyhjentää näytön.
Se on vain tulostettaessa merkkejä
Vaikka tämä on sitä, mitä haluan tehdä.
Okei.
Ja miettiä, miksi tämä piti olla 0 eikä stdin,
joka olisi # define 0,
tämä valittaa, että -
Ennen kun sanoin että siellä on tiedosto kuvaajat, mutta sitten on myös tiedosto *
Tiedoston avainsana on vain yksi kokonaisluku,
katsoo FILE * on koko joukko tavaraa liittyy siihen.
Siksi meidän täytyy sanoa 0 sijaan stdin
on, että stdin on FILE *, joka viittaa asia, joka viittaa tiedoston avainsana 0.
Joten vaikka tänne kun en fopen (argv [1], Saan FILE * takaisin.
Mutta jossain se FILE * on asia, joka vastaa tiedoston avainsana kyseisen tiedoston.
Jos tarkastellaan man sivun auki, joten luulen sinun täytyy tehdä mies 3 auki - nope -
man 2 auki - joo.
Jos katsot sivun auki, auki on kuin alemman tason fopen,
ja se palaa tiedoston todellinen avainsana.
fopen ei nippu tavaraa päällä auki,
joka sen sijaan palauttaa vain, että tiedosto avainsana palauttaa koko tiedoston * osoitin
jonka sisällä on meidän pikku tiedosto avainsana.
Joten standardi viittaa FILE * juttu,
taas 0 viittaa vain tiedoston avainsana standardin itsessään.
>> Kysymyksiä?
[Nauraa] ​​puhalsi läpi.
Selvä. Olemme tehneet. [Nauraa]
>> [CS50.TV]