[Powered by Google Translate] La oss snakke om structs.
Structs gir oss en måte å gruppere en haug med variabler sammen
inn i en fin pakke.
Det er trolig lettest å se et eksempel med en gang,
så vi sier struct,
deretter åpne krøllete brace,
og i dette struct, vil vi ha en int alder,
en char * navn,
og det er det.
Det kan virke merkelig med et semikolon etter en krøllete brace,
men det er faktisk nødvendig med structs.
Enhver gyldig type kan gå i struct definisjonen.
Her har vi brukt en int og en char *,
men du kan også bruke en matrise, av si 100 elementer
eller en annen struct.
Når du bruker structs i C,
du oppretter nye typer
ut av en samling av andre typer.
Her gjør vi en ny type
ut av et heltall og en char *.
Som vi skal se senere, en struct typen
er på mange måter tilsvarer en annen type du er vant til.
Vanligvis vil jeg være sammenligne hvordan en struct typen
er lik et heltall attraksjon.
Mens koden vi skrev er gyldig C,
det er ikke veldig nyttig,
og clang vil gi oss en advarsel.
Husk hvordan structs og dens ligner?
Vel, vi i utgangspunktet bare sa
int,
som ikke er en veldig nyttig linje.
Så la oss faktisk erklære en variabel av denne typen
ved å gi den et navn før semikolon.
Vi kaller variabelen student.
Nå har vi erklært en variabel kalt student
med typen gitt av struct.
Hvordan får vi til variablene inne i struct?
Teknisk navnene for disse variablene
er medlemmer.
Å få tilgang til alle bestemt medlem i en student struct,
du føye til et punkt til variabelen navn,
etterfulgt av navnet på medlemmet du ønsker.
Så her, bare 2 gyldige muligheter
er student.age
og student.name.
Og vi kan gjøre noe sånt
student.age = 12
og student.name = student.
Hva nå hvis vi ønsket å gjøre en ekstra student?
Du kanskje tror å kopiere og lime inn disse linjene
og endre student til student 2 eller noe,
og som vil fungere,
men teknisk, student og student 2
har ikke samme type.
Se, vil du ikke være i stand til å tilordne dem til hverandre.
Dette er fordi, så langt,
din struct har vært anonym.
Vi trenger å gi den et navn.
For å gjøre det, setter vi navnet på struct
etter ordet struct.
student,
etterfulgt av definisjonen.
Vi kan fortsatt umiddelbart erklære en variabel av typen
struct student, som vi gjorde før.
Vi kaller det S1
Ved å gi struct et navn,
Vi kan nå bruke struct student
i nesten nøyaktig samme måte ville vi bruke int.
Så vi kan erklære en variabel av typen struct student,
som
struct student S2.
Som matriser, structs gi en snarvei initialisering syntaks,
så vi kan si, struct student S2
lik
venstre krøllete 3 brace, S2.
Her vil S2.age være 3,
og S2.name vil peke på S2.
Tenk på alle de tingene du kan gjøre med en int typen
og de fleste av dem kan du gjøre med en struct student type.
Vi kan bruke en struct student som en type funksjon parameter.
Vi kan bruke struct student innsiden av en ny struct.
Vi kan ha en peker til en struct student.
Vi kan gjøre størrelsen på struct student.
Struct student er en type
akkurat som int er en type.
Vi kan også tildele S1 til S2
siden begge er av samme type, slik at vi kan gjøre
S1 = S2.
Hva skjer hvis vi gjør
S1.age = 10?
Har S2 endring i det hele tatt?
Igjen, tenk på de structs bare som vanlige heltall.
Hvis vi tildeler noen int X til noen int Y,
som X = Y
og deretter endrer X,
som i X + +,
endrer Y i det hele tatt?
Y endrer ikke her, og så heller ikke S2 ​​ovenfor.
S2.age er fortsatt tre.
Men merk at når du tilordner en struct til en annen,
alle pekere fremdeles peker til det samme,
siden de var bare kopiert.
Hvis du ikke vil at pekere til å bli delt,
må du manuelt håndtere det,
kanskje ved malicking en blokk med minne for en av pekere til å peke på
og kopiere data over.
Det kan være irriterende å måtte skrive struct student overalt.
Ved hjelp av en type def, kan vi gjøre
typen def
struct
og vi kaller det student.
Nå kan vi bruke student overalt
at vi pleide å bruke struct student.
Denne typen def er en anonym struct
og kaller det student.
Men hvis vi også holde studenten identifikator
ved siden av ordet struct, som i typedef struct student,
vi kunne bruke både struct student og student hverandre nå.
De trenger ikke engang å ha samme navn.
Vi kunne skrive def struct student til Bob
og deretter struct student og Bob
ville være utskiftbare typer.
Uavhengig av type def,
vi trenger identifikator ved siden struct
hvis definisjonen av struct
er rekursiv.
For eksempel,
typen def struct node
og det vil bli definert som en int val
og det vil ha en peker som peker til en annen struct node.,
som i struct node * neste.
Og så får vi kalle det node.
Dette struct er rekursiv,
siden definisjonen av struct node inneholder innenfor det
en peker til en struct node.
Legg merke til at vi har å si struct node * neste
innsiden av definisjonen av struct node,
siden den typen def ikke er ferdig ennå å tillate oss å forenkle dette
å bare node * neste.
Du vil lære mer om structs som ligner på dette
når du arbeider med koblede lister og trær.
Hva om structs i en funksjon?
Dette er også helt gyldig.
Vi kunne ha
annullere funk
som tar som et argument,
student s
og gjør noe med det student.
Og så kan vi sende den som student struct som så.
Func av S1 fra før.
Struct oppfører
nøyaktig som et heltall ville når sendes til en funksjon.
Func mottar en kopi av S1
og kan derfor ikke endre S1;
heller, bare kopien av det som er lagret i S.
Hvis du vil at funksjonen skal kunne endre S1,
func må ta en student * S,
og du må passere S1 etter adresse, som så.
Student * S, funk & S1.
Det er en annen grunn til å passere etter adresse her.
Hva om vår struct inneholdt 100 felt?
Hver eneste gang vi passerer en student til funk,
vårt program må kopiere alle de 100 felt i funk argument S,
selv om den bruker aldri de aller fleste av dem.
Så selv om funk ikke tenkt på å endre student,
hvis kan fortsatt være verdifullt å passere adresse.
Ok, hva om vi ønsker å skape en peker til en struct?
Vi kunne gjøre noe sånt
student * S
lik malloc
Størrelsen student.
Legg merke til at størrelsen på fortsatt fungerer her.
Så hvordan skal vi nå få tilgang til alder medlem
av blokken at S peker?
Du kanskje først tenker å gjøre
* S.age = 4,
men dette vil ikke helt fungerer.
Siden dette vil virkelig bli tolket som
* S.age i parentes = 4,
som ikke engang kompilere,
siden S er ikke en struct eller snarere en peker til en struct,
og så prikken ikke vil fungere her.
Vi kunne gjøre
(* S). Alder = 4
men parentes kan bli irriterende og forvirrende.
Heldigvis har vi et spesielt pilen operatør
som ser noe sånt
S-> alder = 4.
Disse to måtene å referere alder
er likeverdige
og vi ikke egentlig trenger pilen operatør,
men det gjør ting ser bedre.
Siden S er en peker til noen blokk av minnet som inneholder den struct,
du kan tenke på S> alder som følge Pekerpilen
og ta tak i alderen medlem.
Så hvorfor skal vi noen gang structs?
Det er definitivt mulig å komme unna med bare primitive heltall,
chars, pekere og lignende
som vi er vant til;
i stedet for S1 og S2 før,
Vi kunne ha hatt alder1, age2, NAME1 og NAME2
alle på separate variabler.
Dette er greit med bare 2 studenter,
men hva om vi hadde 10 av dem?
Og hva hvis i stedet for bare 2 felt,
studenten struct hadde 100 felt?
GPA, kurs, hårfarge, kjønn og så videre.
I stedet for bare 10 structs, trenger vi 1000 separate variabler.
Også vurdere en funksjon
som tar det struct med 100 felt med sin eneste argument
og skriver ut alle felt.
Hvis vi ikke bruker en struct,
hver eneste gang vi kaller denne funksjonen,
vi trenger å passere på alle 100 variabler,
og hvis vi har 100 variabler for student 1,
og 100 variabler for student 2,
vi trenger å være sikker på at vi ikke tilfeldigvis passerer noen variabler fra student 1
og noen variabler fra student 2.
Det er umulig å gjøre det feil med en struct,
siden alle 100 variabler som er med i en enkelt pakke.
Bare et par avsluttende merknader:
Hvis du har forstått alt opp til dette punktet, flott.
Resten av videoen er bare for fullstendighet skyld.
Fordi structs kan holde alle typer pekeren,
de kan også holdfunksjon pekere.
Hvis du er kjent med objektorientert programmering,
Dette er en måte å bruke structs å programmere i et objektorientert stil.
Mer på funksjonspekere på et annet tidspunkt.
Også, noen ganger kan du ha 2 structs
hvis definisjoner avhengig av hverandre.
For eksempel,
vi kunne ha struct A,
som er definert som
en peker til en struct B,
struct B * X,
og nå kan vi ha en struct B
som er definert som en peker
til en struct A,
struct A * Y.
Men dette vil ikke kompilere,
siden struct B finnes ikke på det tidspunktet struct A blir kompilert.
Og hvis vi bytter struct A og struct B,
da ville vi bare bli sittende igjen med det samme problemet;
denne gangen, med struct En ikke eksisterende.
For å løse dette, kan vi skrive
struct B;
før definisjonen av struct A.
Dette kalles en fremtidsrettet erklæring.
Dette kan bare kompilatoren vet at
struct B er en gyldig type som vil bli fullt ut definert senere eller andre steder.
Mitt navn er Rob Bowden, og dette er CS50.
[CS50.TV]