[Powered by Google Translate] [Artikel 5 - meer gemaklik]
[Rob Bowden - Harvard Universiteit]
[Hierdie is CS50. - CS50.TV]
>> Soos ek gesê het in my e-pos, daar is 'n baie dinge wat jy kan gebruik
anders as die toestel om werklik te doen om die probleem stelle.
Ons beveel aan dat jy dit doen in die toestel net omdat dan kan ons jou help om meer maklik
en ons weet hoe alles gaan om te werk.
Maar as 'n voorbeeld van waar jy dinge kan doen as, sê, het jy nie toegang hê
tot 'n toestel of wat jy wil om te werk in die Science Center kelder -
wat eintlik hulle het die toestel te
as jy wil enige plek werk.
Een voorbeeld hiervan is het jy gesien / gehoor van SSH?
SSH is basies net soos verbinding na iets.
Eintlik, reg nou is ek in die toestel SSHed.
Ek het nog nooit direk in die toestel werk.
Hier is die toestel, en as jy kyk hier neer wat jy sien hierdie IP-adres.
Ek het nog nooit in die toestel self werk;
Ek kom altyd tot 'n iTerm2 venster / terminale venster.
Jy kan SSH aan dat die IP-adres, ssh jharvard@192.168.129.128.
Ek onthou dat die getal baie maklik, want dit is so 'n mooi patroon.
Maar dit sal my vra vir my wagwoord, en nou is ek in die toestel.
Basies, op hierdie punt, as jy oopgemaak het 'n terminaal binnekant van die toestel self,
hierdie koppelvlak, maar jy sal dit gebruik, is presies dieselfde
as die koppelvlak ek met behulp van hier, maar nou is jy SSHed.
Jy hoef nie SSH na die toestel.
Een voorbeeld van 'n ander plek waar jy kan SSH is ek is redelik seker dat jy by verstek -
Oh. Groter.
Almal van julle moet by verstek FAS rekeninge op die FAS-bedieners.
Vir my, ek sou SSH tot rbowden@nice.fas.harvard.edu.
Dit gaan jou dat die eerste keer te vra, en jy sê ja.
My wagwoord is net gaan na my FAS wagwoord wees.
En so moet julle nou, ek SSHed na die mooi bedieners, en ek kan enigiets doen wat Ek wil hier.
'N baie van die klasse wat jy kan neem, soos 124, gaan jou goed oplaai hier
om werklik jou probleem stelle.
Maar sê dat jy nie toegang tot jou apparaat.
Dan kan jy dinge doen, soos hier sal dit sê -
Dit is net ons deel van die vrae.
Dit sal jou vra om dit te doen in die toestel.
In plaas daarvan sal ek doen dit net op die bediener.
Ek gaan om te rits.
Die probleem gaan wees dat jy gebruik om die gebruik van iets soos gedit
of wat ook al binnekant van die toestel.
Jy nie gaan om dit te hê op die FAS-bediener.
Dit is net almal gaan na hierdie tekstuele koppelvlak te wees.
Sodat jy kan óf een, probeer om 'n teks editor wat hulle hoef te leer.
Hulle het Nano.
Nano is gewoonlik redelik maklik om te gebruik.
Jy kan gebruik om jou pyle en tik gewoonlik.
So dit is nie moeilik nie.
As jy wil om te kry regtig fancy wat jy kan gebruik Emacs,
wat ek moet seker nie oopgemaak het, want ek weet nie eens hoe om te sluit Emacs.
Beheer X, Control-C? Ja.
Of jy kan gebruik Vim, dit is wat ek gebruik.
En so wat is jou opsies.
As jy nie wil hê om dit te doen, kan jy ook, as jy kyk na manual.cs50.net -
Oh.
Op 'n rekenaar, kan jy SSH met behulp van PuTTY,
wat jy gaan moet apart aflaai.
Op 'n Mac, kan jy net by verstek gebruik Terminal of jy kan aflaai iTerm2,
wat soos 'n mooi, fancy Terminal.
As jy na manual.cs50.net sien jy 'n skakel na Notepad + +,
is wat jy kan gebruik op 'n rekenaar.
Dit kan jy SFTP van Notepad + +, wat is basies SSH.
Wat dit sal laat jy nie wysig jou lêers plaaslik,
en dan wanneer jy wil om hulle te red, sal dit red nice.fas
waar jy kan dan hardloop hulle.
En die ekwivalent op 'n Mac gaan wees TextWrangler.
So dit kan jy doen dieselfde ding.
Dit kan jy wysig lêers plaaslik en stoor dit op nice.fas,
waar jy kan dan hardloop hulle.
So as jy ooit vas sonder 'n toestel, moet jy hierdie opsies
nog steeds nie jou probleem stelle.
Die een probleem gaan wees dat jy nie gaan die CS50 biblioteek te hê
omdat nice.fas nie by verstek.
Jy kan óf aflaai die CS50 biblioteek -
Ek dink nie ek moet op hierdie punt.
Jy kan óf die aflaai van die CS50 biblioteek en kopieer dit na nice.fas,
of ek dink op hierdie punt ons nie gebruik dit nie in elk geval.
Of as ons dit doen, kan jy vir die tyd wat dit vervang met
die implementering van die funksies in die CS50 biblioteek in elk geval.
So wat moet nie dat baie van 'n beperking.
En dis dit.
>> Ek gaan terug na die toestel nou, ons sal alles doen wat in die toestel.
Op soek na ons afdeling van die vrae aan die begin, soos ek gesê het in my e-pos,
ons het om te praat oor die een kort jy veronderstel was om te kyk.
Ons het die Aansturing & Pype en hierdie drie vrae.
>> Tot watter stroom funksies soos skryf printf nie by verstek?
So stroom. Wat is 'n stroom?
'N stroom is basies soos dit is net 'n paar -
Dit is nie eens 'n bron van 1s en 0S.
Die stroom wat dit vra hier is standaard uit.
En so standaard uit 'n stroom wat wanneer jy skryf nie,
dit verskyn op die skerm.
Standaard uit, deur die stroom, beteken dit dat jy net skryf 1s en 0s om dit,
en die ander kant van die standaard uit lees net van daardie stroom.
Dit is net 'n string van 1s en 0S.
Kan u skryf aan strome of jy kan lees van strome
afhangende van wat die stroom is.
Die ander twee standaard strome is standaard en standaard fout.
Standaard in wanneer jy GetString, is dit wag vir jou insette stuff.
So is dit wag vir jou, dit is eintlik wag op standaard in,
wat is werklik wat jy kry wanneer jy tik op die sleutelbord.
Jy tik in standaard.
Standaard fout is basies gelykstaande aan standaard uit,
maar dit is gespesialiseerde in dat wanneer jy druk standaard fout,
jy veronderstel is om net druk fout boodskappe na die
sodat jy kan onderskei tussen gereelde boodskappe gedruk op die skerm
teenoor fout boodskappe, afhangende van of hulle na standaard uit of standaard fout.
Lêers.
Standard uit, standaard en standaard fout is net spesiale strome,
maar regtig 'n lêer, wanneer jy 'n lêer oopmaak, is dit 'n stroom van grepe
waar jy kan net lees van daardie stroom.
U, vir die grootste deel, kan net dink van 'n lêer as 'n stroom van grepe.
So, wat strome skryf hulle nie by verstek? Standard uit.
>> Wat is die verskil tussen> en >>?
Het iemand kyk na die video vooraf? Okay.
> Gaan wees hoe jy redirect in lêers,
en >> ook gaan uitset te lei in lêers,
maar dit plaas gaan toe te voeg aan die lêer.
Byvoorbeeld, kom ons sê ek foutief gebeur hier,
en binnekant van foutief is die enigste dinge kat, kat, hond, vis, hond.
Een opdrag wat jy by die command line is die kat,
wat net gaan om te druk wat in 'n lêer.
So wanneer ek sê kat foutief, dit gaan kat, kat, hond, vis, hond te druk. Dit is al die kat doen.
Dit beteken dat dit gedruk standaard uit kat, kat, hond, vis, hond.
As ek in plaas wil hê dat om te lei na 'n lêer, kan ek gebruik> en lei dit ongeag die lêer is.
Ek bel die lêer lêer.
So nou as ek ls, sal ek sien ek het 'n nuwe lêer met die naam lêer.
En as ek dit oopmaak, gaan dit presies wat kat sit op die command line.
So nou as ek doen wat weer, dan is dit gaan om die uitset te lei in die lêer,
en ek gaan presies dieselfde ding om te hê.
So tegnies, dit heeltemal overrode wat ons gehad het.
En ons sal sien as ek foutief, het ek hond.
Nou as ons kat foutief in die lêer weer, gaan ons die nuwe weergawe met die hond verwyder te hê.
So is dit heeltemal oorheers dit.
In plaas daarvan, as ons >>, dit gaan lêer te voeg.
Nou, die opening van die lêer, sien ons ons het net die dieselfde ding gedruk twee keer
want dit is daar een keer, dan het ons aangeheg aan die oorspronklike.
So dit is wat> en >> doen.
Is die volgende een vra - Dit maak nie vra oor dit.
>> Die ander een wat ons het, is <, wat, indien> aansture standaard uit,
<Gaan word redirect standaard.
Kom ons kyk of ons 'n voorbeeld.
Ek kan skryf een ware vinnig.
Kom ons neem 'n lêer, hello.c.
Relatief maklik lêer.
Ek is net om 'n string en dan druk "Hallo" wat die string Ek het nou net ingeskryf was.
So hallo en dan hom / hallo.
Nou is dit waarna my iets in te voer,
wat beteken dat dit wag op die dinge wat aangegaan word standaard.
So gaan wat ek wil in standaard. Ons is net gaan om te sê Hello, Rob!
Dan is dit die druk standaard Hallo, Rob!
As ek dit doen / hallo. En dan aanstuur,
jy kan net vir nou Aansturing van 'n lêer.
So as ek in sommige lêer, txt, en ek het Rob,
as ek hallo hardloop en dan lei die lêer txt in / hello, dit gaan om te sê Hello, Rob! onmiddellik.
Wanneer dit kry eerste GetString en dit wag op standaard in,
standaard is nie langer wag op die sleutelbord data te kry ingeskryf.
In plaas daarvan, het ons getrek standaard in te lees van die lêer txt.
En so het dit gaan lees van die lêer txt, wat net die lyn Rob,
en dan is dit gaan Hello, Rob te druk!
En as ek wou, kon ek dit ook doen. / Hallo <txt
en dan die standaard daarop dat dit druk, wat Hallo, Rob!
Ek kan jou verwys na wat in sy eie lêer.
Ek sal net noem die lêer hello - Nee, ek sal nie, want dit is die uitvoerbare - txt2.
Nou, is txt2 gaan om die uitset van / hello. <Txt, wat gaan wees Hallo, Rob te hê!
>> Vrae?
>> Okay. So, hier is ons 'n pyplyn.
Pype is die laaste eenheid van die Aansturing.
>> Oh. Ek dink een eenheid van die Aansturing is as in plaas van> jy 2>
wat redirecting standaard fout.
So as iets na standaard fout, sou dit nie sit in die txt2.
Maar let as ek dit doen 2>, dan is dit nog steeds druk Hallo, Rob! die command line
omdat ek net standaard fout redirecting, ek is nie redirecting standaard.
Standaard fout en standaard uit is anders.
As jy wou eintlik skryf aan die standaard fout,
dan kan ek dit verander fprintf na stderr te wees.
So printf, by verstek, druk op die standaard uit.
As ek wil na standaard fout met die hand te druk, dan moet ek fprintf gebruik
en spesifiseer wat ek wil uit te druk.
As maar ek het fprintf stdout, dan is dit basies gelykstaande aan printf.
Maar fprintf standaard fout.
So nou, as ek skakel dit in txt2, Hello, Rob! is nog steeds op die command line gedruk
aangesien dit om gedruk op die standaard fout en ek net redirecting standaard uit.
As ek nou standaard fout aanstuur, nou is dit nie gedruk kry, en txt2 gaan wees Hallo, Rob!
So, nou, kan jy druk jou werklike foute te standaard fout
en druk jou gereelde boodskappe standaard uit.
En dus wanneer jy die program loop, kan jy hardloop dit as / hello. Hierdie tipe met die 2>
sodat jou program gaan om normaal te loop,
maar enige fout boodskappe wat jy kry wat jy later kan kyk in jou fout log,
sodat foute, en dan later kyk en jou foute lêer sal enige foute wat gebeur het.
>> Vrae?
>> Die laaste een is pyp, wat jy kan dink as die neem van die standaard uit een opdrag
en maak dit die standaard van die volgende opdrag.
'N voorbeeld hier echo is 'n command line ding
wat net gaan om te eggo wat ek het as sy argument. Ek sal nie kom aanhalings.
Echo blah, blah, blah is net blah, blah, blah te druk.
Voor, toe ek gesê het, ek het Rob in 'n txt lêer te sit
omdat ek net kan aanstuur txt-lêers, in plaas, / as ek eggo Rob
en dan pyp dit in / hello, wat ook die dieselfde soort van ding doen.
Dit is die uitvoer van hierdie opdrag, echo Rob,
en gebruik dit as die inset vir / hallo.
Jy kan dink dit as eerste aanstuur echo Rob in 'n lêer
en dan insette in / Hello dat lêer wat was net outputted.
Maar dit neem om die tydelike lêer uit die prentjie.
>> Vrae oor wat?
>> Die volgende vraag is gaan om dit te betrek.
Wat pyplyn kan jy gebruik om die getal van unieke name in 'n lêer genaamd names.txt te vind?
Die opdragte gaan ons hier wil gebruik is uniek, so Uniq, en dan toilet.
Jy kan 'n mens Uniq doen om werklik te kyk na wat dit beteken,
En dit is net gaan aangrensende ooreenstem met lyne van die insette te filtreer.
En die mens toilet gaan die newline, woord, en byte tellings vir elke lêer te druk.
En die laaste een wat ons gaan wil gebruik is 'n soort,
wat gaan net lyne van txt-lêer sorteer.
As Ek maak 'n paar txt lêer, names.txt, en dit is Rob, Tommy, Joseph, Tommy, Josef, RJ, Rob,
wat ek hier wil doen is om die getal van unieke name in hierdie lêer vind.
So, wat moet die antwoord wees? >> [Student] 4. >> Ja.
Dit moet 4 sedert Rob, Tommy, Joseph, RJ is die enigste unieke name in hierdie lêer.
Die eerste stap, as ek net doen woord reken op names.txt,
dit is eintlik vertel my alles.
Dit is eintlik druk - laat ons sien, man wc - newlines, woorde, en byte telling.
As ek maar net omgee lyne, dan kan ek net doen wc-l names.txt.
So dit is 'n stap 1.
Maar ek wil nie na wc-l names.txt omdat names.txt net al die name bevat,
en ek wil uit te filtreer enige nie-uniek.
So as ek doen Uniq names.txt, beteken dit nie heeltemal gee my wat ek wil hê
omdat die gedupliseer name is nog steeds daar.
Hoekom is dit? Hoekom is Uniq nie doen wat ek wil?
[Student] Die duplikate is nie [onhoorbaar] >> Ja.
Onthou die man bladsy vir Uniq sê filter aangrensende passende reëls.
Hulle is nie aangrensende, so dit sal hulle filtreer nie.
As ek sorteer hulle eerste soort names.txt gaan al die duplikaat lyne saam te stel.
So nou soort names.txt is.
Ek gaan om te wil om dit te gebruik as die inset na Uniq | Uniq.
Dit gee my Josef, RJ, Rob, Tommy,
en ek wil om dit te gebruik as die inset na wc-l,
wat gaan om te gee my 4.
Soos dit sê hier, wat kan pyplyn jy gebruik?
Jy kan 'n baie van die dinge doen soos die gebruik van 'n reeks instruksies
waar jy die uitset van een opdrag as die insette tot die volgende opdrag.
'N baie van die dinge, 'n baie slim dinge wat jy kan doen.
>> Vrae?
Okay.
Dis dit vir pype en herlei.
>> Nou gaan ons na die werklike dinge, die kodering dinge.
Binnekant van die PDF, sien jy hierdie opdrag,
en jy wil om hierdie opdrag uit te voer in jou toestel.
wget is die opdrag, in wese, net om iets van die Internet
so wget en hierdie URL.
As jy na hierdie URL in jou browser, sou dit om die lêer te laai.
Ek het net gekliek op dit, sodat dit vir my die lêer afgelaai.
Maar skrif wget van daardie ding binnekant van die terminale
is net gaan om dit af te laai in jou terminale.
Ek het section5.zip, en jy wil section5.zip te rits,
wat gaan gee jy 'n gids met die naam section5,
wat gaan al die lêers wat ons gaan gebruik vandag binnekant van dit te hê.
As hierdie programme se lêer name dui daarop, hulle is 'n bietjie buggy,
so jou doel is om uit te vind waarom die gebruik van gdb.
Nie almal het hulle afgelaai / weet hoe om hulle te kry afgelaai
in hul toestel? Okay.
>> Running ./buggy1, sal dit sê Segmentasie skuld (kern gestort),
wat enige tyd kry jy 'n segfault, dit is 'n slegte ding.
Onder watter omstandighede kry jy 'n segfault?
[Student] ontwysing 'n null-aanwijzer. >> Ja. So wat is 'n voorbeeld.
Ontwysing 'n null pointer jy gaan 'n segfault te kry.
Wat 'n segfault middel is om jou geheue is te raak, moet jy raak nie.
So ontwysing 'n null pointer raak adres 0,
en basies alle rekenaars deesdae sê dat die adres 0 geheue wat jy moet raak nie.
So dit is waarom ontwysing 'n null-aanwijzer resultate in 'n segfault.
As jy gebeur nie inisialiseer nie 'n wyser, dan is dit 'n gemors waarde,
en so as jy probeer om dereference dit, in alle waarskynlikheid jy raak geheue
dit is in die middel van nêrens.
As jy toevallig te kry gelukkig en die vullis waarde
gebeur om te verwys na iewers op die stapel of iets,
dan wanneer jy dereference dat die wyser wat jy nie geïnisialiseer,
niks verkeerd gaan.
Maar as dit verwys na, sê, iewers tussen die stapel en die hoop,
of dit wys net iewers wat nie gebruik word deur jou program nie,
dan moet jy raak geheue wat jy moet raak nie en jy segfault.
Wanneer jy skryf 'n rekursiewe funksie en dit recurses te veel keer
en jou stapel groei te groot en die stapel bots in die dinge
dat dit nie bots met, jy raak geheue wat jy moet raak nie,
sodat jy segfault.
Dit is wat 'n segfault is.
>> Dit is ook dieselfde rede dat as jy het 'n string soos -
laat ons gaan terug na die vorige program.
In hello.c-Achievement net gaan om iets anders te maak.
char * s = "hello world!";
As ek * s = iets of e [0] = 'X';
so maak hello, / Hello, hoekom het daardie segfault?
Waarom het hierdie segfault?
Wat sou jy verwag om te gebeur?
As ek gedoen het printf ("% s \ n", s), wat sou jy verwag om gedruk te word?
[Student] X hello. >> Ja.
Die probleem is dat wanneer jy verklaar dat 'n string soos hierdie,
is 'n wyser wat gaan om te gaan op die stapel,
en wat s dui op hierdie string wat vervat is in 'n lees-alleen geheue.
Dus, deur net die naam, read-only memory, moet jy kry die idee
dat as jy probeer om te verander wat in lees-alleen geheue is,
jy doen iets wat jy nie behoort te doen het met die geheue en jy segfault.
Dit is eintlik 'n groot verskil tussen char * s en char s [].
So char s [], nou hierdie string gaan word op die stapel geplaas,
en die stapel is nie lees-alleen, wat beteken dat dit heeltemal fyn werk.
En dit doen.
Onthou dat wanneer ek char * s = "hello world!", S self is op die stapel
maar se punte om iewers anders, en dit gebeur iewers anders lees-alleen te wees.
Maar char s [] is net iets op die stapel.
So dit is nog 'n voorbeeld van 'n segfault gebeur.
>> Ons sien dat ./buggy1 gelei in 'n segfault.
In teorie, moet jy nie kyk na buggy1.c onmiddellik.
In plaas daarvan, sal ons kyk na dit deur gdb.
Let daarop dat wanneer jy Segmentering skuld (kern gestort),
jy hierdie lêer oor hier genoem kern.
As ons ls-l, sal ons sien dat die kern is gewoonlik 'n redelik groot lêer.
Dit is die aantal grepe van die lêer, sodat dit lyk asof dit is 250-iets kilogrepe.
Die rede hiervoor is dat dit wat die kern dump eintlik
is wanneer jou program crashes, die toestand van die geheue van jou program
net kry in hierdie lêer gekopieer en geplak.
Dit word gestort in daardie lêer.
Hierdie program, terwyl dit hardloop, 'n geheue gebruik van ongeveer 250 kilogrepe gebeur het,
en so dit is wat het in hierdie lêer gestort.
Nou kan jy kyk na daardie lêer as ons dit doen gdb buggy1 kern.
Ons kan net doen gdb buggy1, en dit sal net begin gdb gereeld,
deur buggy1 aangesien sy insette lêer.
Maar as jy dit doen gdb buggy1 kern, dan is dit is spesifiek gaan om te begin gdb
deur te kyk op daardie kern lêer.
En jy sê buggy1 middel gdb weet dat kern lêer kom van die buggy1 program.
So gdb buggy1 kern gaan bring ons dadelik
na die plek waar die program gebeur te beëindig.
Ons sien hier Program met sein 11, segmentering skuld beëindig.
Ons gebeur om 'n lyn van die vergadering, wat is waarskynlik nie baie nuttig om te sien.
Maar as jy tik bt of sleepspoor, dit gaan om die funksie te wees
wat gee ons die lys van ons huidige stapel rame.
So sleepspoor. Dit lyk of ons net twee stapel rame.
Die eerste is ons belangrikste stapel raam,
en die tweede is die stapel raam vir hierdie funksie wat ons gebeur te wees in,
wat lyk soos ons net die vergadering kode vir.
So laat ons gaan terug in ons belangrikste funksie,
en te doen wat ons kan raam 1 doen, en ek dink dat ons ook kan doen,
maar ek het byna nooit doen af ​​- of up. Ja.
Op en af. Up bring jy een stapel raam, af bring jy 'n stapel raam.
Ek is geneig om nooit te gebruik dat.
Ek net sê spesifiek raam 1, wat gaan aan die raam gemerk 1.
Frame 1 gaan om ons in te bring in die hoof stapel raam,
en dit sê hier die reël van die kode wat ons gebeur te wees.
As ons wou nog 'n paar reëls van die kode, kan ons sê lys,
en dit is gaan ons al die reëls van die kode om dit te gee.
Die lyn wat ons segfaulted op 6:
if (strcmp ("CS50 rotse", bevat SPASIES [1]) == 0).
Indien dit nie voor die hand liggend is nie, kan jy dit direk van hier net deur te dink hoekom dit segfaulted.
Maar ons kan neem dit 'n stap verder en sê, "Waarom sou bevat SPASIES [1] segfault?"
Let's print bevat SPASIES [1], en dit lyk soos dit se 0x0, wat is die null pointer.
Ons strcmping CS50 rotse en null, en so wat gaan segfault.
En waarom is bevat SPASIES [1] null?
[Student] Omdat ons nie gee dit 'n command-line argumente.
Ja. Ons het nie gee dit 'n command-line argumente.
So ./buggy1 gaan net bevat SPASIES [0] wees ./buggy1.
Dit gaan nie om 'n bevat SPASIES [1], so wat gaan segfault.
Maar as ek doen in plaas daarvan, net CS50, dit gaan om te sê jy 'n D
want dit is wat dit veronderstel is om te doen.
Looking by buggy1.c, dit veronderstel is om te druk "Jy kry 'n D" -
As bevat SPASIES [1] is nie "CS50 rotse", "Jy kry 'n D", anders "Jy kry 'n A!"
So as ons wil 'n A, ons moet dit as die waarheid met mekaar te vergelyk,
wat beteken dat dit kan vergelyk word met 0.
So bevat SPASIES [1] moet wees "CS50 rotse".
As jy wil om dit te doen op die command line, moet jy \ die ruimte te gebruik om te ontsnap.
So CS50 \ rotse en jy kry 'n A!
As jy nie die back slash doen, waarom dit nie werk nie?
[Student] Dit is twee verskillende argumente. >> Ja.
Bevat SPASIES [1] gaan wees CS50, en bevat SPASIES [2] gaan wees rotse. Okay.
>> Nou ./buggy2 gaan weer segfault.
In plaas daarvan om dit oop te maak met sy kern lêer, ons sal net oop te maak buggy2 direk,
so gdb buggy2.
Nou as ons net ons program te hardloop, dan is dit gaan om te sê Program ontvang sein SIGSEGV,
wat is die segfault sein, en dit is waar dit gebeur het om te gebeur.
Soek by ons sleepspoor, sien ons dat ons in die funksie oh_no,
wat geroep is deur die funksie Dinky, wat deur die funksie binky genoem is,
wat deur die hoof geroep is.
Ons kan ook sien die argumente vir hierdie funksies.
Die argument te Dinky en binky was 1.
As ons die lys die funksie oh_no, sien ons dat oh_no net doen char ** s = NULL;
* S = "boom";
Waarom sou dit misluk?
[Student] Jy kan nie dereference die null pointer? >> Ja.
Dit is net te sê s is NULL, ongeag of wat gebeur met 'n char **
wat, afhangende van hoe jy dit interpreteer, kan dit 'n wyser na 'n wyser na 'n string
of 'n skikking van stringe.
Dit is s is NULL, so * s is ontwysing 'n null pointer,
en so dit gaan om te crash.
Dit is een van die vinnigste maniere waarop jy kan segfault.
Dit is net waarby 'n null pointer en onmiddellik segfaulting.
Dit is wat oh_no doen.
As ons gaan op 'n raam, dan gaan ons te kry in die funksie wat genoem oh_no.
Ek nodig het dat om af te doen.
As jy nie 'n opdrag betree en jy net druk Enter weer
dit sal net herhaal die vorige opdrag wat jy geloop het.
Ons is in raam 1.
Listing hierdie raam, ons sien hier is ons funksie.
Jy kan getref lys weer, of jy kan lys 20 en dit sal 'n lys van meer.
Die funksie Dinky sê as ek 1, dan gaan jy na die oh_no funksie,
anders gaan die slinky funksie.
En ons weet ek is 1 omdat ons gebeur om te sien hier
Dinky is genoem met die argument 1.
Of jy kan net druk moet ek en dit sal sê ek is 1.
Ons is tans in Dinky, en as ons gaan op 'n ander raam, ons weet dat ons sal eindig in binky.
Up. Nou is ons in binky.
Listing hierdie funksie - die lys van voor die helfte van my af te sny -
dit het begin asof ek 0, dan gaan ons noem dit oh_no, anders Dinky noem.
Ons weet ek was 1, sodat dit het Dinky.
En nou is ons terug in die hoof, en die belangrikste is net gaan na int i = rand ()% 3;
Dit is net gaan om te gee jou 'n ewekansige getal wat is óf 0, 1 of 2.
Dit gaan binky met daardie getal te noem, en dit sal terugkeer 0.
Kyk na hierdie,
net loop sonder dat dit onmiddellik deur middel van die program met die hand,
jy sal 'n breek punt stel by die hoof, wat beteken dat wanneer ons hardloop die program
jou program loop tot dit 'n breek punt tref.
So het die loop van die program, sal dit hardloop en dan sal dit die belangrikste funksie getref en ophou om te hardloop.
Nou is ons binnekant van die hoof, en stap of langs gaan om ons in te bring na die volgende lyn van die kode.
Jy stap of volgende kan doen.
Slaan volgende, nou het ek is rand ()% 3, sodat ons kan die waarde van i print,
en dit sal sê ek is 1.
Nou is dit maak nie saak of gebruik ons ​​volgende of stap.
Ek dink dit saak in die vorige een, maar ons wil om volgende te gebruik.
As ons gebruik stap, ons stap in die funksie, wat beteken 'n blik op die werklike ding
wat gebeur binnekant van binky.
As ons gebruik die volgende, dan beteken dit gaan oor die funksie
en gaan jy na die volgende lyn van kode in ons belangrikste funksie.
Reg hier op hierdie lyn, ek was waar dit gesê rand ()% 3;
as ek stap, sou dit in die implementering van die rand
en kyk na wat daar gebeur, en ek kon stap vir stap deur die rand-funksie.
Maar ek gee nie om oor die rand-funksie.
Ek wil net om te gaan na die volgende lyn van die kode in die belangrikste, so ek gebruik die volgende.
Maar nou doen ek sorg oor die binky funksie, so ek wil om te stap in daardie.
Nou is ek in binky.
Die eerste reël van die kode gaan om te sê as (i == 0), Ek neem 'n stap,
sien ons ons beland by Dinky.
As ons lys dinge, sien ons dat dit nagegaan is i = 0.
ek is nie gelyk aan 0, so dit het aan die ander toestand,
wat gaan Dinky (i) te roep.
Jy kan deurmekaar raak.
As jy net kyk na hierdie lyne direk, kan jy dink as (i == 0),
okay, dan het ek 'n stap en nou is ek by Dinky (i),
jy kan dink wat beteken i = 0 of iets.
Nee, dit beteken net dat hy weet dit direk kan vashou aan die lyn Dinky (i).
Omdat ek nie 0 is nie, is die volgende stap gaan nie by die ander aan die einde.
Anders is nie 'n lyn wat dit gaan om te stop by.
Dit is net gaan om te gaan na die volgende lyn kan dit eintlik te voer, wat Dinky (i).
Stepping in Dinky (i), sien ons as (i == 1).
Ons weet i = 1, sodat wanneer ons stap, ons weet dat ons gaan om te eindig in oh_no
omdat i = 1 noem die funksie oh_no, wat jy kan stap in,
wat gaan stel char ** s = nul en onmiddellik "boom".
En dan eintlik op soek na die implementering van buggy2,
hierdie, ek is maar net 'n ewekansige getal - 0, 1 of 2 - roeping binky,
wat as ek 0 dit noem oh_no, anders is dit keurig noem, wat kom hier.
As ek 1, bel oh_no, anders roep slinky, wat hier kom,
as ek 2, bel oh_no.
Ek het nie eens dink daar is 'n manier -
Is daar iemand sien 'n manier van die maak van hierdie 'n program wat sal nie segfault?
Want tensy ek mis iets, as ek 0, sal jy onmiddellik segfault,
anders gaan jy na 'n funksie wat as ek is 1 wat jy segfault,
anders gaan jy na 'n funksie waar as ek is 2 segfault.
So maak nie saak wat jy doen, jy segfault.
>> Ek dink een manier om van die vasstelling van dit sou wees in plaas van doen char ** s = NULL,
jy kan malloc ruimte vir daardie string.
Wat ons kan doen malloc (sizeof) - sizeof wat?
[Student] (char) * 5? >> Is dit reg is?
Ek neem aan dit sal werk as ek eintlik dit het, maar dit is nie wat ek soek nie.
Kyk na die tipe van s. Kom ons voeg int *, so int * x.
Ek sou doen malloc (sizeof (int)).
Of as ek wou 'n skikking van 5, sal ek doen (sizeof (int) * 5);
Wat as ek 'n int **?
Wat sou ek malloc?
[Student] Grootte van die wyser. >> Ja. (Sizeof (int *));
Dieselfde ding hier onder.
Ek wil (sizeof (char *));
Dit gaan om ruimte toe te ken vir die wyser wat verwys na "boom".
Ek hoef nie ruimte toe te ken vir "boom" self
want dit is basies gelykstaande aan wat ek vroeër gesê het
char * x = "boom".
"Boom" bestaan ​​reeds. Dit gebeur om te bestaan ​​in die lees-alleen streek van die geheue.
Maar dit bestaan ​​reeds, wat beteken dat hierdie lyn van kode, indien s is 'n char **
* s is 'n char * en jy die opstel van hierdie char * om te verwys na "boom".
As ek wou "BOOM" in s te kopieer, dan sou ek moet ruimte vir s toe te ken.
Ek sal doen * s = malloc (sizeof (char) * 5);
Hoekom 5?
Hoekom nie 4? Dit lyk soos "boom" is 4 karakters. >> [Student] Die null karakter.
Ja. Al jou snare gaan die null karakter nodig.
Nou kan ek iets doen soos strcat - Wat is die funksie vir die kopiëring van 'n string?
[Student] CPY? >> Strcpy.
man strcpy.
So strcpy of strncpy.
strncpy is 'n bietjie veiliger omdat jy kan spesifiseer presies hoeveel karakters,
maar hier is dit maak nie saak nie, want ons weet nie.
So strcpy en kyk in die argumente.
Die eerste argument is ons bestemming.
Die tweede argument is ons bron.
Ons gaan om te kopieer in ons bestemming * s die pointer "BOOM".
Hoekom wil jy dalk om dit te doen met 'n strcpy in plaas van net wat ons gehad het voordat
* s = "boom"?
Daar is 'n rede waarom jy dalk wil om dit te doen, maar wat is die rede?
[Student] As jy iets wil verander in "BOOM". >> Ja.
Nou kan ek doen iets s [0] = 'X';
want se punte aan die hoop en dat spasie op die hoop dat s word verwys na
is 'n wyser om meer spasie op die hoop wat die stoor van "boom".
So hierdie kopie van "boom" word gestoor in die hoop.
Daar is tegnies twee kopieë van "BOOM" in ons program.
Daar is die eerste een wat net deur hierdie "boom" string konstante,
en die tweede afskrif van "boom", strcpy die afskrif van "boom" geskep het.
Maar die afskrif van "boom" word gestoor op die hoop en die hoop wat jy is vry om te verander.
Die hoop het nie lees-alleen, so dit beteken dat s [0]
gaan om jou te laat die waarde van "boom" te verander.
Dit gaan om jou te laat die karakters verander.
>> Vrae?
Okay.
>> Beweeg op tot buggy3, laat se gdb buggy3.
Ons het net hardloop dit en ons sien ons kry 'n segfault.
As ons sleepspoor, is daar slegs twee funksies.
As ons gaan in ons belangrikste funksie, sien ons dat ons op hierdie lyn segfaulted.
Dus net op soek na hierdie lyn, int lyn = 0 vir (; fgets hierdie dinge nie gelyk aan NULL;
lyn + +).
Ons vorige raam is genoem _IO_fgets.
Sal jy sien dat 'n baie met ingeboude C funksies,
dat wanneer jy die segfault, sal daar regtig 'n kriptiese funksie name
soos hierdie _IO_fgets.
Maar dit gaan in verband te bring hierdie fgets oproep.
Iewers in hier, is ons segfaulting.
As ons kyk na die argumente fgets, kan ons druk buffer.
Kom ons druk as 'n O, nee.
Print gaan nie werk presies soos ek dit wil.
Kom ons kyk na die werklike program.
Buffer is 'n karakter skikking. Dit is 'n karakter verskeidenheid van 128 karakters.
So wanneer ek sê print buffer, gaan dit die 128 karakters te druk,
wat ek dink is wat verwag word.
Wat ek soek is druk die adres van die buffer,
maar dit beteken nie regtig vir my sê baie.
So toe ek toevallig om te sê hier x buffer, dit wys my 0xbffff090,
wat, as jy onthou van vroeër of 'n sekere punt, Oxbffff is geneig om 'n stapel-ish streek.
Die stapel is geneig om iewers te begin net onder 0xc000.
Net deur hierdie adres te sien, ek weet dat buffer gebeur op die stapel.
Weer te begin my program, hardloop, buffer, wat ons gesien het, was om die volgorde van die karakters
wat pretty much betekenisloos.
Dan druk-lêer, wat beteken lêer lyk?
[Student] null. >> Ja.
Lêer is 'n soort lêer *, so dit is 'n wyser,
en die waarde van die wyser is leeg.
So fgets gaan om te probeer om te lees dat die wyser op 'n indirekte manier,
maar sodat wyser om toegang te verkry tot, moet dit dereference dit.
Of, ten einde toegang tot wat dit behoort te wys word, is dit dereferences dit.
So dit is 'n null-aanwijzer en dit segfaults ontwysing.
Ek kon weer begin het.
As ons breek op ons belangrikste punt en hardloop,
die eerste reël van die kode is char * filename = "nonexistent.txt";
Dit moet 'n mooi groot wenk as waarom hierdie program nie.
Tik die volgende bring my by die volgende reël, waar ek hierdie lêer oopmaak,
en dan het ek dadelik in ons lyn, waar ek jou eenmaal getref volgende, gaan dit segfault.
Is daar iemand wil gooi uit 'n rede waarom ons kan segfaulting word?
[Student] Lêer bestaan ​​nie. >> Ja.
Dit is veronderstel om 'n wenk
dat wanneer jy 'n lêer opening van wat jy nodig het om seker te maak dat die lêer bestaan.
So hier is, "nonexistent.txt";
Wanneer ons fopen lêernaam vir lees, moet ons dan om te sê
if (lêer == null) en sê printf ("Lêer bestaan ​​nie!"
of - nog beter - lêernaam); terugkeer 1;
So nou het ons gaan om te sien of dit is NULL
voor eintlik voort en probeer om te lees van daardie lêer.
Ons kan remake dit net dat werke te sien.
Ek bedoel 'n nuwe reël in te sluit.
So nou nonexistent.txt bestaan ​​nie.
Jy moet altyd kyk vir hierdie soort van ding.
Jy moet altyd kyk om te sien of fopen terugkeer NULL.
Jy moet altyd kyk om seker te maak dat malloc nie terugkeer NULL,
of anders wat jy segfault.
>> Nou buggy4.c.
Hardloop. Ek vermoed dit is wag vir insette of dalk oneindige herhaling.
Ja, dit is oneindige herhaling.
So buggy4. Dit lyk soos ons is oneindige herhaling.
Ons kan by die hoof breek, hardloop ons program.
Gdb, so lank as wat die afkorting wat jy gebruik het, is ondubbelsinnig
of spesiale afkortings wat hulle verskaf vir jou,
dan kan jy n volgende te gebruik in plaas van om uit te tik die volgende al die pad.
En nou dat ek getref is n een keer, ek kan net druk Enter om voort te gaan volgende
in plaas van om te tref 'n Enter, n Enter, n Enter.
Dit lyk asof ek in 'n soort van loop wat die oprigting array [i] na 0.
Dit lyk soos ek nog nooit is uit te breek van hierdie lus.
As ek i druk, so ek is 2, dan sal ek volgende gaan.
Ek sal druk ek, ek is 3, dan sal ek volgende gaan.
Ek sal druk ek en ek is 3. Volgende, druk ek, ek is 4.
Eintlik, print sizeof (array), so die grootte van die skikking is 20.
Maar dit lyk of daar is 'n paar spesiale gdb opdrag om te gaan totdat iets gebeur.
Dit is soos die opstel van 'n toestand op die waarde van die veranderlike. Maar Ek kan nie onthou wat dit is.
So as ons gaan -
Wat sê jy? Wat het jou laat opkom?
[Student] Is vertoon ek byvoeg - >> Ja. So wys ek kan help.
As ons net i vertoon, sal dit sit hier wat die waarde van i is
so ek hoef dit nie uit te druk elke keer.
As ons net gaan hou langs, dan sien ons 0, 1, 2, 3, 4, 5, 0, 1, 2, 3, 4, 5, 0, 1, 2, 3, 4, 5.
Iets gaan verskriklik verkeerd, en ek is stel na 0.
Looking by buggy4.c, ons sien al wat gebeur is int array [5];
(i = 0; i <= sizeof (array); i + +)
array [i] = 0;
Wat sien ons dat is verkeerd hier?
As 'n wenk, toe ek die gdb buggy4 besig was om te doen - laat ons hoof breek, run -
Ek print sizeof (array) het net om te sien wat die toestand is waar ek moet uiteindelik breek uit.
Waar's ek? Het ek loop?
Ek het nog nie verklaar nie.
So print sizeof (array) en dit is 20,
wat na verwagting sedert my skikking van grootte 5 en dit is 5 heelgetalle,
so die hele ding moet 5 * sizeof (int) bytes, waar sizeof (int) is geneig om te wees 4.
So sizeof (array) is 20.
Wat moet dit wees?
[Student] verdeel deur sizeof (int). >> Ja, / sizeof (int).
Dit lyk asof daar is nog steeds 'n probleem hier. Ek dink dit moet net wees <
want dit is pretty much altyd <en nooit <=.
Nou laat ons dink oor die rede waarom dit was eintlik gebreek.
Is daar iemand waarom raaiskote was ek weer tot 0 deur elke iterasie van die lus?
Die enigste ding wat binnekant van hier wat gebeur is dat die skikking met die [i] 0 gestel word.
So een of ander manier, is hierdie lyn van die kode wat veroorsaak dat ons int i ingestel word na 0.
[Student] Kan dit wees, want dit is oorheersende die geheue van hierdie deel van die i
wanneer dit dink dit is die volgende skikkingselement? >> [Bowden] Ja.
Wanneer gaan ons verby die einde van ons verskeidenheid,
een of ander manier dat die ruimte wat ons oorheersende oorheersende van die waarde van i.
En so, as ons kyk na buggy4, breek belangrikste, hardloop,
Kom ons druk die adres van i.
Dit lyk soos dit is bffff124.
Laat ons nou druk die adres van array [0]. 110.
Wat van [1]? 114.
[2] 118.
11c, 120. array [5] bfff124.
So array [5] het die dieselfde adres as ek, wat beteken dat array [5] i.
As hulle het dieselfde adres, hulle is dieselfde ding.
So wanneer ons array [5] tot 0, is ons die opstel i tot 0.
En as jy dink oor dit in terme van die stapel,
Int ek vir die eerste keer verklaar, wat beteken ek kry 'n paar ruimte op die stapel.
Dan array [5] toegeken is, so is daar dan 20 bytes word toegeken op die stapel.
Ek kry dus eerste keer toegeken is, dan hierdie 20 bytes kry toegeken.
So i gebeur reg voor die skikking,
en as gevolg van die manier, soos ek verlede week gesê, waar dit tegnies die stapel af groei,
wanneer jy die werf in 'n skikking, is ons gewaarborg dat die 0 posisie in die skikking
altyd gebeur voor die eerste posisie in die skikking.
Dit is 'n soort van hoe ek verlede week het dit uitgetrek.
Let daarop dat ons aan die onderkant adres 0 en aan die bokant ons adres Max.
Die stapel is altyd groeiende.
Kom ons sê ons toeken i.
Ons toeken heelgetal i, wat beteken laat ons net sê hier heelgetal i kry toegeken.
Dan sal ons ken ons verskeidenheid van 5 heelgetalle, wat beteken dat onder daardie,
sedert die stapel groei af, kry die 5 heelgetalle toegeken.
Maar gevolg van hoe skikkings werk, ons gewaarborg dat die eerste posisie in die skikking
altyd 'n adres wat minder is as die tweede ding in die skikking.
So array posisie 0 het altyd na die eerste gebeur in die geheue,
terwyl array posisie 1 het gebeur nadat
en skikking posisie 2 het daarna gebeur,
wat beteken dat die skikking posisie 0 iewers hier onder gebeur,
array posisie 1 hierbo wat sou gebeur
want beweeg op 'n hoër die adresse sedert die maksimum adres is hier.
So array [0] sit hier, array [1] tot hier, array [2] tot hier, array [3] hier.
Let op hoe voordat ons toegeken integer i al die pad tot hier,
soos ons beweeg verder en verder in ons verskeidenheid, word ons al hoe nader en nader aan ons heelgetal i.
Dit gebeur net so dat array [5], wat is een posisie buite ons verskeidenheid,
is presies waar heelgetal i gebeur toegeken word.
So wat is die punt waar ons gebeur te wees slaan die ruimte op die stapel
wat is toegeken vir integer i, en ons wat aan 0.
>> Dit is hoe dit werk. Vrae? Ja.
[Student] Never mind. Okay.
[Student] Hoe vermy jy hierdie soort van foute?
Hierdie soort van foute? Gebruik nie C as jou programmeertaal.
Gebruik 'n taal wat skikking grense nagaan.
So lank as wat jy versigtig, jy hoef net te vermy gaan verby die grense van jou skikking.
[Student] So hier toe ons verby die grense van jou verskeidenheid -
[Bowden] Dit is waar dinge begin skeefloop. >> [Student] O, okay.
Solank as wat jy bly in die geheue geallokeer vir jou array, jy is fine.
Maar C geen fout kontrole. As ek dit doen array [1000], sal dit graag net verander wat ook al gebeur -
Dit gaan na die begin van die skikking, dan is dit gaan 1000 poste na en stel dit aan 0.
Dit nie doen enige kontrolering dat oh, dit is eintlik nie 1000 dinge in dit.
1000 is 'n manier as wat ek moet verander,
terwyl Java of iets wat jy kry array perke indeks
of indeks buite grense uitsondering.
Dit is die rede waarom 'n baie hoër vlak tale het hierdie dinge
waar as jy gaan buite die grense van die skikking, u versuim om
sodat jy nie kan verander dinge onder julle
en dan dinge gaan veel erger as net om 'n uitsondering
sê dat jy gaan na die einde van die skikking.
[Student] En so moet ons het net verander die <= net <? >> [Bowden] Ja.
Dit moet wees <sizeof (array) / sizeof (int);
sedert sizeof (array) is 20, maar ons wil net 5. >> [Student] Reg.
Nog vrae? Okay.
>> [Student] Ek het 'n vraag. >> Ja.
[Student] Wat is die werklike verskeidenheid veranderlike?
[Bowden] Soos wat array?
Array self is 'n simbool.
Dit is net die adres van die begin van die 20 bytes dat ons verwysingstegnieke.
Jy kan dink aan dit as 'n wyser nie, maar dit is 'n konstante wyser.
So gou as dinge saamgestel, het die veranderlike skikking nie meer bestaan ​​nie.
[Student] So hoe werk dit die grootte van die skikking?
Grootte van die skikking verwys na die grootte van daardie blok dat simbool verwys na.
Wanneer ek iets doen soos printf ("% p \ n" skikking);
laat se loop dit.
Wat ek het net verkeerd doen?
Array "array" verklaar.
O, hier.
Kletteren is slim, en dit gebeur om op te let dat ek verklaar dat die skikking as 5 elemente
maar ek kruip in posisie 1000.
Dit kan doen nie, want dit is net konstantes.
Dit kan net so ver gaan merk dat ek gaan buite die grense van die skikking.
Maar let voor wanneer ons het ek verkeerd wees,
dit kan nie bepaal hoeveel waardes i kan neem,
so dit kan nie bepaal dat ek gaan na die einde van die skikking.
Dit is net kletteren synde slim.
>> Maar nou maak buggy4. So wat anders doen ek verkeerd?
Implisiet verklaar biblioteek funksie printf ".
Ek gaan om te wil # sluit.
Okay. Nou hardloop buggy4.
Die druk van die waarde van die skikking soos ek hier gedoen het, druk dit as 'n wyser
afdrukke iets wat lyk soos hierdie - bfb8805c - wat is 'n paar adres
dis in die stack-ish streek.
Array self is soos 'n wyser, maar dit is nie 'n werklike pointer,
sedert 'n gereelde pointer ons kan verander.
Skikking is net 'n paar konstante. Die 20 blokke van geheue begin by adres 0xbfb8805c.
So bfb8805c deur hierdie adres +20- of ek dink -20 -
is al die geheue geallokeer vir hierdie skikking.
Skikking, is die veranderlike self nie gestoor oral.
Wanneer jy die opstel van die samesteller - hand golf op dit -
maar die vertaler sal net gebruik waar dit weet skikking te wees.
Dit weet waar daardie skikking begin,
en so dit kan net altyd dinge doen in terme van offsets van daardie begin.
Dit hoef nie 'n veranderlike self skikking te verteenwoordig.
Maar wanneer ek iets doen soos int * p = array p is nou 'n wyser wat daarop dui dat die skikking,
en nou p eintlik nie bestaan ​​op die stapel.
Ek is vry om p te verander. Ek kan doen p = malloc.
So het dit oorspronklik verwys na verskeidenheid, nou is dit wys na 'n ruimte op die hoop.
Ek kan dit nie doen skikking = malloc.
As kletteren is slim, sal dit op my skreeu regs af die vlermuis.
Eintlik is ek redelik seker dat gcc sal dit ook doen.
So verskeidenheid tipe int [5] "is nie oordraagbaar nie.
Jy kan nie iets aan 'n verskeidenheid tipe
want die skikking is net 'n konstante.
Dit is 'n simbool wat verwysings daardie 20 grepe. Ek kan dit nie verander nie.
>> [Student] En waar is die grootte van die skikking gestoor?
[Bowden] Dit is nie gestoor oral. Dit is wanneer dit die opstel van.
So waar is die grootte van die skikking gestoor?
Kan jy net gebruik sizeof (array) binnekant van die funksie wat die skikking self verklaar word.
So as ek dit doen paar funksie, cat, en wat ek doen (int array [])
printf ("% d \ n", sizeof (array));
en dan af Ek noem hier cat (array);
binnekant van hierdie funksie laat loop dit.
Dit is kletteren slim weer.
Dit vertel my dat sizeof array funksie parameter
die grootte van 'int *' sal terugkeer.
Dit sou 'n fout wees as dit is nie wat ek wou om te gebeur.
Kom ons eintlik afskakel Werror.
Waarskuwing. Waarskuwings is fine.
Dit sal nog steeds stel solank dit het 'n waarskuwing.
Gaan. / A.out is uit te druk 4.
Die waarskuwing wat gegenereer is 'n duidelike aanduiding van wat verkeerd geloop het.
Hierdie int skikking net gaan sizeof (int *) te druk.
Selfs as ek array [5] hier, dit is nog steeds net gaan sizeof (int *) te druk.
So gou as jy verby dit in 'n funksie, die onderskeid tussen skikkings en wysers
nie bestaan ​​nie.
Dit gebeur om 'n skikking wat op die stapel verklaar is,
maar sodra ons daardie waarde slaag, dat 0xbf blah, blah, blah in hierdie funksie,
dan is dit wyser wys dat die skikking op die stapel.
So dit beteken dat sizeof slegs van toepassing in die funksie wat die skikking verklaar is,
wat beteken dat wanneer jy die opstel van hierdie funksie,
wanneer die geratel gaan deur middel van hierdie funksie, sien skikking is 'n int verskeidenheid van grootte 5.
So hang dit dan sien sizeof (array). Wel, dit is 20.
Dit is eintlik hoe sizeof basies werk vir byna alle gevalle.
Sizeof is nie 'n funksie nie, dit is 'n operateur.
Jy noem dit nie die sizeof funksie.
Sizeof (int), die vertaler sal net vertaal wat aan 4.
Het jy dit? Okay.
>> [Student] So wat is die verskil tussen sizeof (array) in hoof-en foo?
Dit is omdat ons sê sizeof (array), wat van tipe int *
terwyl die skikking af hier is nie van die tipe int *, dit is 'n int verskeidenheid.
>> [Student] So as jy het die parameter in array [] in plaas van int * skikking,
sou dit beteken dat jy nog steeds kan verander array want nou is dit 'n wyser?
[Bowden] Soos hierdie? >> [Student] Ja. Kan jy verskeidenheid binne die funksie nou?
[Bowden] Jy kan verander skikking in beide gevalle.
In beide hierdie gevalle is jy vry om te sê array [4] = 0.
[Student] Maar kan jy array punt na iets anders?
[Bowden] Oh. Ja. In ieder geval - >> [student] Ja.
[Bowden] Die onderskeid tussen array [] en 'n int * verskeidenheid, is daar niemand.
Jy kan ook 'n multi-dimensionele skikking hier
vir 'n paar gerieflike sintaksis, maar dit is nog steeds net 'n wyser.
Dit beteken dat ek vry skikking te doen = malloc (sizeof (int)), en nou iewers anders wys.
Maar net soos hoe dit werk vir ewig en altyd,
hierdie verskeidenheid deur dit te verander na iets anders
verander nie hierdie array hier af, want dit is 'n afskrif van die argument,
dit is nie 'n wyser na daardie argument.
En eintlik, net soos meer aanduiding dat dit presies is dieselfde -
ons reeds gesien het wat druk array druk -
Wat gebeur as ons die druk van die adres van die skikking of die adres van die adres van die skikking
een van dié?
Kom ons ignoreer hierdie een.
Okay. Dit is 'n boete. Dit is nou hardloop / a.out.
Druk skikking, dan druk van die adres van die skikking, is dieselfde ding.
Array net nie bestaan ​​nie.
Dit weet wanneer jy skikking wil druk, moet jy die simbool wat verwys na die 20 bytes wil druk.
Die druk van die adres van die skikking, goed, skikking bestaan ​​nie.
Dit hoef nie 'n adres, sodat dit net druk die adres van die 20 bytes.
So gou as wat jy stel, soos in jou saamgestel buggy4 / a.out.
skikking is nie bestaan ​​nie.
Pointers bestaan. Skikkings nie.
Die blokke van geheue wat die skikking steeds bestaan,
maar die veranderlike verskeidenheid en veranderlikes van daardie soort nie bestaan ​​nie.
Dit is soos die belangrikste verskille tussen skikkings en wysers
so gou as wat jy maak funksie oproepe, daar is geen verskil nie.
Maar binnekant van die funksie wat die skikking self verklaar word, sizeof werk anders
omdat jy die druk van die grootte van die blokke in plaas van die grootte van die tipe,
en jy kan dit nie verander nie, want dit is 'n simbool.
Die druk van die ding en die adres van die ding druk dieselfde ding.
En dit is pretty much dit.
[Student] Kan jy sê dat 'n mens meer tyd?
Ek dalk iets gemis het.
Druk skikking en adres van skikking druk dieselfde ding,
terwyl as jy die druk van 'n wyser teenoor die adres van die wyser,
die een ding druk die adres van die wat jy verwys na,
die ander druk die adres van die wyser op die stapel.
Jy kan 'n wyser verander, jy kan nie 'n skikking simbool verander.
En sizeof wyser gaan om die grootte van daardie tipe wyser te druk.
So int * p sizeof (p) gaan uit te druk 4,
maar int array [5] print sizeof (array) is gaan te druk 20.
[Student] So int array [5] sal druk 20? >> Ja.
Dit is die rede waarom binnekant van buggy4 wanneer dit gebruik word om sizeof (array)
dit besig was om te doen i <20, wat is nie wat ons wou.
Ons wil i <5. >> [Student] Goed.
[Bowden] En dan so gou as jy begin wat in die funksies,
as ons het int * p = array;
binnekant van hierdie funksie, kan ons basies p en verskeidenheid in presies dieselfde manier,
behalwe vir die sizeof probleem en die veranderende probleem.
Maar p [0] = 1, is dieselfde as om te sê array [0] = 1;
En so gou as ons sê cat (array); of foo (p);
binne van die cat funksie, dit is twee keer dieselfde oproep.
Daar is geen verskil tussen hierdie twee oproepe.
>> Almal goed op? Okay.
Ons het 10 minute.
>> Ons sal probeer om te kry deur middel van hierdie Hacker Typer program,
hierdie webwerf, wat gekom het uit verlede jaar of iets.
Dit is net veronderstel om te wees soos jy tik lukraak en dit druk uit -
Wat ook al lêer gelaai gebeur het, is wat dit lyk soos jy tik.
Dit lyk soos 'n soort van die bedryfstelsel-kode.
Dit is wat ons wil uit te voer.
Jy moet 'n program uitvoerbaar met die naam hacker_typer
wat neem in 'n enkele argument, om die lêer te "hacker tipe."
Die loop van die uitvoerbare moet duidelik die skerm
en dan 'n karakter van die vraestel in die lêer elke keer wanneer die gebruiker druk 'n sleutel druk.
So watter sleutel wat jy druk, moet dit weg te gooi en plaas druk van 'n karakter uit die lêer
wat is die argument.
Ek sal pretty much vir jou sê wat die dinge wat ons gaan nodig om te weet.
Maar ons wil om te kyk na die termios biblioteek.
Ek het nog nooit gebruik word om hierdie biblioteek in my hele lewe, so dit het 'n baie minimale doeleindes.
Maar dit gaan om die biblioteek wat ons kan gebruik om weg te gooi nie die karakter wat jy getref
wanneer jy tik in standaard.
So hacker_typer.c, en ons gaan om te wil # sluit.
Op soek na die man bladsy vir termios - ek raai dit se terminale OS of iets -
Ek weet nie hoe om dit te lees.
Kyk na hierdie, sê dit hierdie 2 lêers in te sluit, so sal ons doen.
>> Eerste ding wat die eerste, ons wil te neem in 'n enkele argument, wat is die lêer wat ons behoort te open.
So wat doen wat ek wil doen? Hoe maak ek om te sien ek het 'n enkele argument?
[Student] As argc gelyk aan dit. >> [Bowden] Ja.
So if (argc = 2!) Printf ("Gebruik:% s [lêer oop te maak]").
So nou as ek hardloop sonder die verskaffing van 'n tweede argument - oh, ek nodig het die nuwe lyn -
sien jy sê dit gebruik: / hacker_typer.
en dan die tweede argument moet die lêer wat ek wil oopmaak.
Nou wat moet ek doen?
Ek wil van hierdie lêer te lees. Hoe lees ek van 'n lêer?
[Student] Jy maak dit eerste. >> Ja.
So fopen. Wat beteken fopen lyk?
[Student] Filename. >> [Bowden] Filename gaan wees bevat SPASIES [1].
[Student] En dan wat jy wil om dit te doen met, so die >> [Bowden] Ja.
So as jy nie onthou nie, kan jy net doen man fopen,
waar dit gaan om 'n const char * pad waar die pad is lêernaam,
const char * af.
As jy toevallig nie onthou wat af is, dan kan jy kyk vir die mode.
Binnekant van die man bladsye, die slash karakter is wat jy kan gebruik om te soek vir dinge.
So ek tik / af te soek vir die mode.
N en N is wat jy kan gebruik om fiets te ry deur die search wedstryde.
Hier is dit, sê die argument af punte na 'n string
begin met een van die volgende reekse.
So r, Open teks lêer vir lees. Dit is wat ons wil doen.
Vir die lees, en ek wil op te slaan.
Die ding is gaan na 'n lêer *. Nou wat ek wil om dit te doen?
Gee my 'n tweede.
Okay. Nou wat ek wil om dit te doen?
[Student] Gaan na of dit is NULL. >> [Bowden] Ja.
Enige tyd as jy 'n lêer oopmaak, maak seker dat jy suksesvol is in staat om dit oop te maak.
>> Nou wil ek daardie termios dinge te doen waar ek wil lees eers my huidige instellings
en stoor in iets, dan wil ek my voorkeure te verander
weg te gooi nie 'n karakter wat ek tik,
en dan wil ek daardie instellings te werk.
En dan aan die einde van die program, ek wil terug na my oorspronklike instellings te verander.
So het die struct gaan te wees van die tipe termios, en ek gaan twee van die wil.
Die eerste een gaan wees my current_settings,
en dan gaan hulle my hacker_settings te wees.
Eerste, gaan ek wil my huidige instellings te red,
dan gaan ek wil hacker_settings te werk,
en dan aan die einde van my program, ek wil terugkeer na huidige instellings.
So spaar huidige instellings, die manier wat werk, ons man termios.
Ons sien dat ons hierdie int tcsetattr, int tcgetattr.
Ek slaag in 'n termios struct deur die wyser.
Die manier om dit sal lyk is - I've reeds vergeet wat die funksie is geroep.
Kopieer en plak dit.
So tcgetattr, dan wil ek in die struct dat ek die inligting is op besparing in,
wat gaan wees current_settings,
en die eerste argument is die lêer descriptor vir die ding wat ek wil die eienskappe van te red.
Wat die lêer descriptor is soos enige tyd as jy 'n lêer oopmaak, dit kry 'n lêer descriptor.
Toe ek fopen bevat SPASIES [1], raak dit 'n lêer descriptor wat jy verwys
wanneer jy wil lees of skryf nie.
Dit is nie die lêer descriptor ek hier wil gebruik.
Daar is drie lêer beskrywings wat jy by verstek,
wat is standaard in, standaard uit, en standaard fout.
By verstek, ek dink dit is standaard in is 0, standaard uit 1 en standaard fout is 2.
So, wat wil ek die instellings te verander?
Ek wil die instellings te verander wanneer ek 'n karakter getref,
Ek wil dit dat die karakter om weg te gooi in plaas van druk dit op die skerm.
Wat baan - standaard, standaard uit, of standaard fout -
reageer op dinge wanneer ek tik op die sleutelbord? >> [Student] Standard. >> Ja.
Sodat ek dit kan doen, hetsy 0 of ek kan doen stdin.
Ek kry die current_settings standaard.
>> Nou wil ek hierdie instellings te werk,
so ek sal eers kopieer in hacker_settings wat my current_settings is.
En hoe structs werk is dit sal net kopieer.
Dit afskrifte van al die velde, soos jy sou verwag.
>> Nou wil ek sommige van die velde te werk.
Soek by termios, sal jy het om te lees deur middel van 'n baie van hierdie
net om te sien wat jy wil om te kyk vir,
maar die vlae wat jy gaan om te wil om te kyk vir is echo,
so ECHO Echo insette karakters.
Eerstens wil ek te stel - I've reeds vergeet wat die velde is.
Dit is wat die struct lyk.
So insette modi Ek dink wat ons wil verander.
Ons sal kyk na die oplossing om seker te maak dit is wat ons wil verander.
Ons wil lflag te verander ten einde te verhoed hoef te kyk deur al hierdie dinge.
Ons wil plaaslike modes te verander.
Jy wil hê deur hierdie hele ding te lees om te verstaan ​​waar alles behoort
dat ons wil verander.
Maar dit is binnekant van die plaaslike modes waar ons gaan om te wil om dit te verander.
So hacker_settings.cc_lmode is wat dit genoem word.
c_lflag.
Dit is waar ons in bis-operateurs.
Ons is soort van uit die tyd, maar ons gaan dit regtig vinnig.
Dit is waar ons in bis-operateurs,
waar ek dink ek het 'n tyd lank gelede gesê dat wanneer jy begin handel met vlae,
jy gaan word met behulp van bis-operateur 'n baie.
Elke bietjie in die vlag ooreenstem met 'n soort van gedrag.
So hier is, hierdie vlag het 'n klomp van verskillende dinge, waar almal van hulle beteken iets anders.
Maar wat ek wil doen is om net die bietjie wat ooreenstem met ECHO afskakel.
So om te draai af Ek doen & = ¬ ECHO.
Eintlik, dink ek dit is soos Techo of iets. Ek gaan net weer te keur.
Ek kan dit termios. Dit is net eggo.
ECHO gaan om 'n bietjie.
¬ ECHO gaan beteken dat al die stukkies is ingestel op 1, wat beteken dat al die vlae na ware
behalwe vir die ECHO bietjie.
Deur die beëindiging van my plaaslike vlae met hierdie, beteken dit dat al die vlae wat tans op ware
sal steeds gestel word om ware.
As my ECHO vlag op waar gestel is, dan is dit nie noodwendig op VALS ingestel is op die ECHO vlag.
So hierdie lyn van die kode draai net af die ECHO vlag.
Die ander reëls van die kode, ek sal net kopieer dit in die belang van die tyd en dan verduidelik.
In die oplossing, het hy gesê 0.
Dit is waarskynlik beter om te sê uitdruklik stdin.
>> Let daarop dat ek ook ek doen ECHO | ICANON hier.
ICANON verwys na iets skei, wat beteken kanoniese af.
Wat kanoniese mode middel is gewoonlik wanneer jy tik die command line,
standaard nie verwerk enigiets totdat jy getref newline.
So wanneer jy GetString, jy tik 'n klomp van die dinge, dan is jy getref newline.
Dit is wanneer dit gestuur is standaard.
Dit is die standaard.
Toe ek afskakel kanoniese af, nou elke enkele karakter wat jy druk
wat kry verwerk, wat is gewoonlik soort swak, want dit is stadig om hierdie dinge te verwerk,
wat is die rede waarom dit is goed om dit in die hele lyne te buffer.
Maar ek wil elke karakter te verwerk
want ek wil dit nie om te wag vir my newline te tref
voordat dit verwerk al die karakters wat ek tik.
Dit skakel kanoniese af.
Hierdie dinge beteken net wanneer dit werklik karakters verwerk.
Dit beteken dat dit verwerk onmiddellik, so gou as ek hulle is tik, verwerk hulle.
En dit is die funksie wat die opdatering van my verstellings vir standaard in,
en TCSA middel doen dit sommer nou.
Die ander opsies is wag totdat alles wat tans op die stroom is verwerk.
Wat nie regtig saak nie.
Net nou verander my instellings te wees wat tans in hacker_typer_settings.
Ek dink ek het dit genoem hacker_settings, so laat verander.
Verander alles te hacker_settings.
>> Nou gaan ons aan die einde van ons program om te wil om terug te keer
wat tans binnekant van normal_settings,
wat gaan kyk net soos & normal_settings.
Let op ek het nie verander nie enige van my normal_settings sedert oorspronklik om dit.
Dan net verander hulle terug, ek slaag hulle weer aan die einde.
Dit was die update. Okay.
>> Binnekant van hier sal ek net verduidelik die kode in die belang van die tyd.
Dit is nie dat 'n groot-kode.
Ons sien ons 'n karakter uit die lêer lees. Ons noem dit f.
Nou kan jy man fgetc, maar hoe fgetc is gaan om te werk
dit is net gaan om terug te keer van die karakter wat jy net lees of EOF,
wat ooreenstem met die einde van die lêer of 'n fout gebeur.
Ons is herhaling, die voortsetting van 'n enkele karakter van die lêer te lees,
totdat ons het hardloop uit van die karakters te lees.
En terwyl ons dit doen, ons wag op 'n enkele karakter van standaard.
Elke keer as jy tik iets op die command line,
wat lees in 'n karakter van die standaard.
Dan putchar is net gaan die char Ons lees hier van die lêer na standaard uit te sit.
Jy kan 'n mens putchar, maar dit is net om standaard uit, is dit die druk van die karakter.
Jy kan ook net printf doen ("% c", c), dieselfde idee.
Dit gaan om die grootste deel van ons werk te doen.
>> Die laaste ding wat ons gaan om te wil doen is om net fclose ons lêer.
As jy nie fclose, dis 'n geheugenlek.
Ons wil hê dat die lêer wat ons oorspronklik geopen fclose, en ek dink dit is dit.
As ons, ek het reeds probleme.
Kom ons kyk.
Wat het dit kla oor?
Verwagte "int", maar argument is van die soort 'struct _IO_FILE * ".
Ons sal sien of dit werk.
Slegs toegelaat in C99. Augh. Okay, maak hacker_typer.
Nou kry ons meer bruikbare beskrywings.
So gebruik van onverklaarde identifiseerder 'normal_settings ".
Ek het nie geroep dit normal_settings. Ek het geroep dit current_settings.
So laat verander al van dat.
Nou verby argument.
Ek sal hierdie 0 vir nou.
Okay. / Hacker_typer. Cp.c.
Ek het ook nie duidelik die skerm aan die begin.
Maar jy kan terugkyk na die laaste probleem stel om te sien hoe jy duidelik die skerm.
Dit is net die druk van sommige van die karakters
terwyl dit te doen wat ek wil doen.
Okay.
En dink oor die rede waarom dit nodig is om 0 in plaas van stdin,
wat # define 0,
dit is kla dat -
Voor toe ek gesê het dat daar lêer beskrywings nie, maar dan moet jy ook jou lêer *
'n lêer descriptor is net 'n heelgetal,
terwyl 'n lêer * het 'n hele klomp van die dinge wat verband hou met dit.
Die rede waarom ons moet 0 om te sê in plaas van stdin
is dat stdin is 'n lêer * wat wys na die ding wat verwysingstegnieke lêer descriptor 0.
Sodat selfs hier wanneer ek dit doen fopen (bevat SPASIES [1], ek kry 'n lêer *.
Maar iewers in daardie lêer * is 'n ding wat ooreenstem met die lêer descriptor vir daardie lêer.
As jy kyk na die man bladsy vir 'n oop, so ek dink jy hoef te doen, man 3 oop - nope -
man 2 oop - ja.
As jy kyk op die bladsy vir 'n oop, oop soos 'n laer vlak fopen,
en dit is die terugkeer van die werklike file descriptor.
fopen 'n klomp van die dinge op die top van 'n oop,
wat in plaas van die terugkeer net dat die file descriptor gee 'n hele lêer * wyser
binnekant van wat ons klein file descriptor.
So standaard verwys na die lêer * ding,
terwyl 0 verwys na net die lêer descriptor standaard op sigself.
>> Vrae?
[Lag] blaas deur.
Alles reg. Ons klaar is. [Lag]
>> [CS50.TV]