Structura este un depozit convenabil pentru datele eterogene pe care doriți să le combinați. De exemplu, puteți crea o structură care să descrie parametrii dispozitivului dvs. - setările de rețea, timpul de expirare a somnului, codul său de identificare și așa mai departe, cum ar fi o linie de salut și starea LED-ului. Odată ce toți parametrii sunt stocați într-un singur loc - vor fi întotdeauna vizibili, iar IDE-urile normale vă vor spune câmpurile de structură atunci când le accesați. De asemenea, vom lua în considerare stocarea și recuperarea structurilor din arhivă, precum și transferul acestora pe rețea.
Cum funcționează?
S-ar putea face ceva diferit: declarați doar tipul și faceți variabila mai târziu. Pentru a face acest lucru, am folosi cuvântul cheie typedef și scrieți acest lucru:
Desigur, în ambele variante puteți declara orice număr de instanțe de structuri sau să le creați o serie de ele:
Varianta cu matricea este deosebit de convenabilă pentru serverul din topologia client-server a rețelei - fiecare client își păstrează parametrii proprii în structură, iar pe dispozitivul master există o tabelă de parametri pentru toți clienții sub forma unui șir de structuri.
În principiu, nu există nimic complicat în structuri, iar pe tema serverelor și clienților, am abordat fără probleme un subiect mai interesant:
Depozitarea, transmiterea și sincronizarea structurilor
Pentru mulți, va fi surprinzător faptul că aceste structuri sunt stocate în memorie sub forma unei liste plate, toate câmpurile structurii merg pur și simplu în memorie unul câte unul. Prin urmare, devine posibil să se ocupe de această structură ca și cu o matrice de octeți simplu! Să verificăm, să creați o matrice "deasupra" acestei structuri.
Decalajul inițial este după cum urmează:
sizeof și offsetof
Nu sunt chiar funcții, ci macro-uri încorporate de limbaj C. Să începem cu o dimensiune mai simplă.
Compilatorul înlocuiește toate înregistrările de dimensiunea formei X cu valoarea lungimii X. Pentru X, atât tipul, cât și instanța tipului pot acționa, adică în cazul nostru, puteți înlocui dimensiunea și tipul de structură (dacă o tastăm cu un typedef), iar variabila de structură în sine este: sizeof params_struct sau sizeof params. Va trece prin toate câmpurile structurii, va adăuga lungimile și va da suma, care este lungimea structurii.
offsetof este o macrocomandă reală care ia doi parametri (structura _s_ și câmpul _m_ din ea) și dă poziția acestui câmp în structură, offsetul acestuia față de începutul structurii. Această macrocomandă arată foarte simplu:
Cum funcționează?
Aici trebuie să faceți o mică deviere. Problema este că am considerat cel mai simplu caz, când câmpurile sunt împachetate exact unul după celălalt. Există și alte metode de ambalare, numite "nivelare". De exemplu, puteți da fiecărui câmp un "slot", un număr de 4 octeți sau 8 octeți. Apoi, chiar caracterele vor ocupa 8 octeți, iar dimensiunea totală a structurii va crește, iar toate offseturile se vor mișca și vor deveni multipli ai alinierii. Acest lucru este util în programarea pentru un computer, deoarece din cauza granulării RAM, procesorul este mult mai rapid să extragă din memorie datele aliniate, are nevoie de mai puține operații pentru acesta.
Lucrul cu o serie de structuri
Ok, acum putem reprezenta orice structură sub forma unei mulțimi de octeți și invers. Înțelegi chipul? La noi acum una și aceeași zonă de memorie are roluri "structură" și "dosar". Schimbăm ceva în structură - schimbăm matricele, schimbăm matricea - modificăm structura.
Aceasta este esența procesului! Nu avem o matrice separată, deoarece structura însăși este deja o matrice și pur și simplu adresăm memoria în moduri diferite. Și nu avem cicluri de copiere pentru câmpuri sau octeți, acest ciclu va fi imediat în funcția de transfer.
Acum rămâne doar să înveți cum să lucrezi cu toate astea.
Depozitarea și transferarea structurii
Funcțiile de transmisie de date prin rețea, de obicei, arată aproximativ la fel. Ca transfer de date params, și ca lungimea datelor - sizeof params.
Primirea și restaurarea structurii
Totul este exact la fel. Funcția mea este să citesc matricele din EEPROM: I2C_burst_read (I2Cx, HW_address, addr, n_data, * data). n_data = sizeof params, * data = params:
Nu uitați că scrieți direct octeții recepționați direct în structură. Dacă transmisia este lentă sau nesigură, este logic să scrieți datele într-un buffer temporar și după ce le verificați, transferați-le către structură prin
Prin implementarea acestor metode, vom face o sincronizare convenabilă a două structuri amplasate pe mașini diferite: microcontroler client poate fi cel puțin pe cealaltă parte a globului de pe server, dar structura va trece în continuare la fel de ușor.
Stocarea / restaurarea câmpurilor individuale
Și de ce ne-am uitat la decalajul macro pentru atâta timp? Este foarte convenabil să-l utilizați pentru citirea și scrierea câmpurilor separate ale structurii, de exemplu:
Ei bine și, în general, ar fi destul de bine să faceți împachetări convenabile pentru acest scop.