[Powered by Google Translate] Să vorbim despre struct.
Structs ne oferă o modalitate de a grupa o gramada de variabile împreună
într-un pachet frumos.
Este probabil mai ușor pentru a vedea un exemplu imediat,
asa spunem struct,
deschiderea apoi buclat bretele,
și, în acest struct, vom avea o vârstă int,
un char * nume,
și asta e tot.
Poate părea ciudat, cu un punct și virgulă după o proteză cret,
dar e, de fapt, este necesar, cu struct.
Orice tip valid se poate merge în definiția struct.
Aici, am folosit un int și un char *,
dar ai putea folosi, de asemenea, o serie, de un cuvânt de spus, 100 de elemente
sau chiar un alt struct.
Atunci când utilizați struct în C,
te crearea de noi tipuri de
dintr-o colecție de alte tipuri.
Aici, facem un nou tip de
dintr-un întreg și un char *.
După cum vom vedea mai târziu, un tip struct
este într-o mulțime de moduri echivalente cu orice alt tip ești obișnuit.
De obicei, voi fi comparat modul în care un tip de struct
este similar cu un tip de număr întreg.
În timp ce codul am scris este valabil C,
nu e foarte util,
și zăngănit ne va da un avertisment.
Amintiți-vă cum struct și ei sunt similare?
Ei bine, am spus practic doar
int,
care nu este o linie de mare ajutor.
Deci, haideți să declare, de fapt o variabila de acest tip
dându-i un nume înainte de virgulă.
Vom numi elevul variabila.
Acum, ne-am declarat un student variabilă zisul
cu tipul dat de struct.
Cum ajungem la variabilele din interiorul struct?
Tehnic, numele acestor variabile
sunt membri.
Pentru a accesa orice membru special într-o struct elev,
ai adăuga un punct la numele variabilei,
urmată de numele pe care doriți membru.
Deci, aici, în numai 2 posibilitati valide
sunt student.age
și student.name.
Și putem face ceva de genul
student.age = 12
și student.name = elev.
Acum, ce dacă am vrut sa fac un student secunde?
Ai putea crede că pentru a copia și lipi aceste linii
și schimbați la elev la elev 2 sau ceva,
și că va lucra,
dar punct de vedere tehnic, elev și student 2
nu au același tip.
A se vedea, nu veți fi în măsură să le atribuiți unul pe altul.
Acest lucru se datorează faptului că, până în prezent,
struct dvs. a fost anonim.
Avem nevoie să-i dea un nume.
Pentru a face acest lucru, vom introduce numele struct
după cuvântul struct.
student,
urmată de definiție.
Ne putem declara încă imediat o variabilă de tip
struct elev, așa cum am făcut-o înainte.
Vom numi S1
Prin acordarea struct un nume,
putem folosi acum elev struct
în aproape același mod exact ne-ar folosi int.
Deci, putem declara o variabilă de tip struct elev de,
ca
struct elev S2.
Ca matrice, struct oferă o sintaxă de inițializare de comenzi rapide,
astfel încât putem spune, struct elev S2
este egal cu
stânga cret bretele 3, S2.
Aici, S2.age va fi de 3,
și S2.name va indica S2.
Gândește-te la toate lucrurile pe care le puteți face cu un tip de int
și cele mai multe dintre ele se poate face cu un tip de elev struct.
Putem folosi un student struct ca un tip de un parametru funcție.
Putem folosi elev struct în interiorul unei structuri noi.
Putem avea un pointer la un student struct.
Putem face dimensiunea de student struct.
Elev struct este un tip de
la fel ca int este un tip.
Ne putem atribui, de asemenea, S1 la S2
din moment ce ambele sunt de același tip, astfel încât să putem face
S1 = S2.
Ce se întâmplă dacă facem
S1.age = 10?
Se schimbă S2, la toate?
Din nou, cred că a struct doar ca numere întregi regulate.
Dacă vom atribui unele X int-o oarecare Y int,
cum ar fi X = Y
și apoi schimbați X,
la fel ca în X + +,
se schimbă Y la toate?
Y nu se schimbă aici, și așa nici nu S2 de mai sus.
S2.age este încă 3.
Dar, rețineți că, atunci când atribuirea o struct la alta,
toate indicii încă indică același lucru,
deoarece acestea au fost doar copiate.
Dacă nu doriți ca indicii pentru a fi partajate,
va trebui să se ocupe de manual faptul că,
probabil prin malicking un bloc de memorie pentru una dintre indicii pentru a indica
și copierea datelor de peste.
Ar putea fi enervant de a avea de a scrie elev struct peste tot.
Folosind un tip de def, putem face
Tipul de def
struct
și vom numi elev.
Acum, putem folosi oriunde elev
pe care am folosit pentru a utiliza elev struct.
Acest tip de def e un struct anonim
și o numește elev.
Dar dacă ne ține, de asemenea identificatorul elevului
de lângă cuvântul struct, la fel ca în typedef struct elev,
am putea folosi atât elev și student struct alternativ acum.
Ei nu au nici măcar să aibă același nume.
Am putea scrie def elev struct lui Bob
și apoi struct elev și Bob
ar fi tipuri interschimbabile.
Indiferent de tipul de def,
avem nevoie de identificatorul de lângă struct
dacă definiția struct
este recursiv.
De exemplu,
Tipul de def struct nod
și va fi definit ca un val int
și va avea un pointer care indică un alt nod struct.,
ca și în nod struct * următoare.
Și apoi vom numi nod.
Acest struct este recursiv,
deoarece definiția nod struct conține în ea
un pointer la un nod struct.
Observați că trebuie să spunem struct nod * următor
interiorul definiției nod struct,
deoarece def tipul nu a terminat încă pentru a ne permite de a simplifica acest
la doar * nod următor.
Veți afla mai multe despre struct similare cu aceasta
atunci când se ocupă cu liste legate și copaci.
Ce zici de structs într-o funcție?
Acest lucru este, de asemenea, perfect valabil.
Am putea avea
anula func
care ia ca argument,
studentului s
și face ceva cu acel student.
Și apoi putem să-l dați ca struct student ca asa.
Func de S1 din înainte.
Struct se comportă
exact ca un întreg ar atunci când a trecut la o funcție.
Func primește o copie a S1
și astfel nu poate modifica S1;
mai degrabă, doar copie a acesteia care este stocat în S.
Dacă doriți funcția de a fi capabil de a modifica S1,
funcționarea va trebui să ia o * S elev,
și va trebui să treacă prin adresa S1, la fel ca așa.
Student * S, func & S1.
Mai este un motiv pentru a trece prin adresa aici.
Ce se întâmplă dacă struct nostru conținute 100 de domenii?
De fiecare data cand trecem un student la funcționarea,
Programul nostru are nevoie pentru a copia toate cele 100 de câmpuri într-S argumentul func lui,
chiar dacă nu-l folosește marea majoritate a acestora.
Deci, chiar dacă funcția nu are de gând privind modificarea student,
în cazul în care poate fi încă valoroase pentru a trece prin adresa.
Bine, ce se întâmplă dacă dorim să creăm un pointer la o structura?
Am putea face ceva de genul
Student * S
este egal cu malloc
dimensiunea de student.
Observați că dimensiunea încă mai funcționează aici.
Deci, cum putem accesa acum membru vârsta
de bloc, care la punctele S?
Ai putea crede că primul care a făcut
* S.age = 4,
dar acest lucru nu va funcționa destul.
Din moment ce acest lucru va fi interpretat ca adevărat
S.age * în paranteză = 4,
care nu va compila chiar,
deoarece S nu este un struct sau mai degrabă un pointer la o structura,
și astfel punct nu va funcționa aici.
Am putea face
(* S). Vârstă = 4
dar parantezele pot obține enervant și confuz.
Din fericire, avem un operator de săgeată specială
care arată ceva de genul
S-> varsta = 4.
Aceste 2 moduri de referențiere vârstă
sunt echivalente
și nu avem cu adevărat nevoie vreodată operatorul săgeată,
dar face lucrurile arata mai frumos.
Deoarece S este un pointer la unele bloc de memorie care conține struct,
vă puteți gândi la vârsta S>, dupa cum urmeaza indicatorul săgeată
și apuca membru vârstă.
Deci, de ce ar trebui să folosim vreodată struct?
Este cu siguranță posibil să scape doar cu numere intregi primitive,
caractere, indicii și articole similare
pe care suntem obișnuiți să;
în loc de S1 și S2 înainte,
am putea avea age1, age2, NAME1, NAME2 și
toate la variabile separate.
Acest lucru este bine cu doar 2 studenți,
dar ce se întâmplă dacă am avut 10 dintre acestea?
Și ce dacă în loc de doar 2 câmpuri,
struct student a avut 100 de domenii?
AAP, cursuri, culoarea părului, de gen, și așa mai departe.
În loc de doar 10 struct, avem nevoie de 1000 variabile separate.
De asemenea, ia în considerare o funcție
care ia ca struct cu 100 de domenii, cu argumentul său numai
și imprimă toate domeniile.
Dacă nu am folosi un struct,
de fiecare dată noi numim această funcție,
avem nevoie pentru a trece de la toate cele 100 de variabile,
și dacă vom avea 100 de variabile pentru elev 1,
și 100 de variabile pentru studenți 2,
avem nevoie pentru a fi siguri că nu trece accidental unele variabile de la elev 1
și unele variabile de la elev 2.
Este imposibil de a face această greșeală cu o struct,
deoarece toate variabilele 100 sunt conținute într-un singur pachet.
Doar câteva note finale:
Dacă ați înțeles totul până la acest punct, mare.
Restul video este doar de dragul suplimentar ".
Deoarece struct poate stoca orice tip de pointer,
ele pot deține, de asemenea pointeri la functii.
Dacă sunteți familiarizat cu programarea orientată obiect,
aceasta oferă un mod de a utiliza programul pentru a struct într-un stil orientat obiect.
Mai multe despre pointeri la functii, la un alt moment.
De asemenea, uneori, este posibil să aveți 2 structs
definiții ale căror depind unul de altul.
De exemplu,
am putea avea struct A,
care este definit ca
un pointer la un B struct,
struct B * X,
și acum putem avea o struct B
care este definit ca un pointer
la o struct A,
struct A * Y.
Dar acest lucru nu se va compila,
deoarece B struct nu exista la momentul în care struct A este în curs de compilare.
Și dacă vom schimba struct A și B struct,
atunci am fi tocmai a plecat cu aceeași problemă;
de data aceasta, cu struct A existent nu.
Pentru a rezolva acest lucru, putem scrie
struct B;
înainte de definirea struct A.
Aceasta se numește o declarație înainte.
Acest lucru va permite doar să știu că compilatorul
struct B este un tip valid, care va fi pe deplin definit mai târziu sau în altă parte.
Numele meu este Rob Bowden, iar acest lucru este CS50.
[CS50.TV]