1 / 39

I. Structuri

I. Structuri. Tipul struct. colecţie de variabile (membri) accesate printr-un nume comun ar putea fi şi variabile independente atunci de ce le grupăm? logica aplicaţiei impune tratarea lor comună mai uşor de gestionat variabilele respective. Reprezentare internă.

kevina
Download Presentation

I. Structuri

An Image/Link below is provided (as is) to download presentation Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

Presentation Transcript


  1. I. Structuri

  2. Tipul struct • colecţie de variabile (membri) • accesate printr-un nume comun • ar putea fi şi variabile independente • atunci de ce le grupăm? • logica aplicaţiei impune tratarea lor comună • mai uşor de gestionat variabilele respective

  3. Reprezentare internă • membrii sunt plasaţi în memorie unul după altul • la adrese consecutive • adresa de început a primului membru = adresa de început a structurii • adresa de început a fiecărui membru = suma dimensiunilor membrilor precedenţi • sau nu?

  4. Exemplu struct S { char a,b; int c; double d; char e; short f; };

  5. Exemplu (cont.) S s; printf("Dimensiune structura: %d\n",sizeof(s)); printf("start:\t%p\n",&s); printf("a:\t%p\t%2d\n",&s.a,(int)&s.a-(int)&s); printf("b:\t%p\t%2d\n",&s.b,(int)&s.b-(int)&s); printf("c:\t%p\t%2d\n",&s.c,(int)&s.c-(int)&s); printf("d:\t%p\t%2d\n",&s.d,(int)&s.d-(int)&s); printf("e:\t%p\t%2d\n",&s.e,(int)&s.e-(int)&s); printf("f:\t%p\t%2d\n",&s.f,(int)&s.f-(int)&s);

  6. Rezultat - exemplu de afişare Dimensiune structura: 24 start:0012FF4C a:0012FF4C0 b:0012FF4D1 c:0012FF504 d:0012FF548 e:0012FF5C16 f:0012FF5E18

  7. Interpretare • variabila c începe la deplasament 4 • în loc de 2 • variabila f începe la deplasament 18 • în loc de 17 • dimensiunea structurii - 24 • ar fi trebuit să fie 17 • sau 20, dacă ţinem cont de cele de mai sus

  8. Alinierea adreselor (1) • deplasamentul fiecărui membru este multiplu de dimensiunea sa • motivaţie • transferurile cu memoria sunt mai simple • ocuparea memoriei este mai uşor de gestionat • efect - între membrii structurii pot apărea spaţii nefolosite

  9. Alinierea adreselor (2) • dezavantaj • consum de memorie mărit • în principiu, ne putem permite • alinierea poate fi dezactivată ProjectPropertiesC/C++Code GenerationStruct Member Alignment: 1 Byte (în loc de Default)

  10. Dimensiunea structurii (1) • de multe ori este mai mare decât suma dimensiunilor membrilor • consecinţă a alinierii adreselor • pot fi spaţii neutilizate între unii membri • poate fi un spaţiu neutilizat la finalul structurii

  11. Dimensiunea structurii (2) • exemplu S t[2]; printf("\nt[0]: %p\nt[1]: %p\n",&t[0],&t[1]); • rezultat afişare t[0]:0012FF14 t[1]:0012FF2C

  12. De ce ne interesează? • calculul adreselor elementelor din tablourile de structuri • vezi anterior • sunt şi alte situaţii în care informaţia este importantă • exemplu - citirea unei imagini dintr-un fişier în format BMP

  13. Structură header BMP typedef struct { unsigned char magic[2]; unsigned long filesz; unsigned short creator1; unsigned short creator2; unsigned long bmp_offset; } bmpfile_header_t;

  14. Citire header bmpfile_header_t bh; FILE *fBMP=fopen("f.bmp","r"); // citire header fisier fread(&bh,sizeof(bh),1,fBMP); // ... fclose(fBMP);

  15. Probleme sizeof(bh)=16 • în fişier nu există aliniere • trebuie citiţi 14 octeţi • deplasamentele câmpurilor sunt la rândul lor incorecte • e mai sigur să citim membrii unul câte unul

  16. Funcţii cu parametri structuri • limbajul C nu permite transmiterea structurilor ca parametri • doar pointeri la structuri • limbajul C++ o permite, dar cazul său îl vom discuta mai târziu • accesarea membrilor • pe stivă avem doar un pointer, nu toată structura • atenţie la aliniere

  17. Returnarea valorilor din funcţii • unde trebuie pus rezultatul pentru a fi returnat? • în mod uzual - registrul eax • sau al/ax pentru dimensiuni mai mici • dar dacă vrem să returnăm un tip mai mare de 4 octeţi?

  18. Unde apare problema • tipurile elementare nu depăşesc 4 octeţi • tipul double este returnat prin unitatea de virgulă mobilă • nu ne interesează aici • structuri • nu pot fi returnate în limbajul C • doar pointeri la structuri • dar în C++ este posibil

  19. Soluţii (1) • depinde de compilator • aici discutăm despre Visual Studio • structură cu dimensiune până în 8 octeţi • regiştrii edx (partea mai semnificativă) şi eax • ce înseamnă parte mai semnificativă? • Intel - adresare little-endian • partea mai semnificativă dintr-un operand - cea aflată la o adresă mai mare în memorie

  20. Soluţii (2) • structură cu dimensiune mai mare de 8 octeţi • se mai transmite un parametru ascuns (nu apare în lista de parametri) • adresa structurii care trebuie completată cu rezultatul • acest parametru este plasat la adresa [ebp+8] • deci primul parametru "real" se găseşte acum la [ebp+12]

  21. II. Referinţe şi pointeri

  22. Ce este o referinţă • nu apare în limbajul C • introdusă în C++ • reprezintă un alt nume (alias) pentru o variabilă deja existentă

  23. Declarare int a; int &b=a; • b este o referinţă pentru a • a nu se confunda cu operatorul adresă • moduri incorecte de declarare: int &b; int &b=20;

  24. Utilizare int a; int &b=a; a=3; b=5; printf("%d\n",a); • rezultat afişat: 5 • deci a fost modificată chiar variabila a

  25. Reprezentare internă (1) • ne putem gândi la două posibilităţi • compilatorul foloseşte două nume diferite pentru aceeaşi locaţie de memorie • b este de fapt un pointer către adresa variabilei a

  26. Reprezentare internă (2) a=3; _asm { mov b,5 } printf("%d\n",a); • rezultat afişat: 3 • dacă erau două nume pentru aceeaşi locaţie, s-ar fi afişat 5

  27. Reprezentare internă (3) a=3; _asm { mov eax,b mov dword ptr [eax],5 } printf("%d\n",a); • rezultat afişat: 5

  28. Reprezentare internă (4) • deci b este de fapt o variabilă separată • pointer - conţine adresa variabilei a • compilatorul ascunde aceste detalii • se doreşte să privim b ca pe un alt nume pentru a • putem verifica prin afişarea adreselor variabilelor a şi b

  29. int a; int &b=a; int *p1,*p2; p1=&a; p2=&b; printf("%p\n%p\n",p1,p2); rezultat afişare 0012FF60 0012FF60 deci C++ raportează aceeaşi adresă Preluare adrese din C++

  30. int a; int &b=a; int *p1,*p2; _asm { lea eax,a mov p1,eax lea eax,b mov p2,eax } printf("%p\n%p\n",p1,p2); rezultat afişare 0012FF60 0012FF54 adresele sunt de fapt diferite Preluare adrese din ASM

  31. Utilitate (1) • referinţele sunt deci pointeri • avantaj - mai uşor de lucrat decât cu pointerii • nu mai trebuie să folosim operatorii & (adresă) şi * (dereferenţiere)  mai puţine greşeli • dezevantaj - mai puţin flexibile • o referinţă este legată de o singură variabilă pe toată durata existenţei sale

  32. Utilitate (2) • referinţele nu pot deci înlocui pointerii în toate situaţiile • exemplu - parcurgerea elementelor unui tablou char s[]="abcd",*p; for(p=s;*p!='\0';p++) // ... • unde sunt totuşi utile? • cel mai des folosite - parametri pentru funcţii

  33. Referinţe ca parametri (1) void f(int &m) {//...} int x; f(x); • parametrul m este o referinţă pentru variabila x • orice modificare asupra lui m se reflectă asupra lui xtransfer prin referinţă

  34. Referinţe ca parametri (2) • atenţie la ce înseamnă referinţă void f(int &m) {//...} f(5); • eroare la compilare - referinţa este o adresă • la fel ca în cazul pointerilor

  35. Referinţe vs. pointeri (1) • care este de preferat? • unde le putem folosi pe ambele - referinţe • sintaxă mai simplă • în unele situaţii putem folosi doar pointeri • cum stau lucrurile la nivelul limbajului de asamblare? • nici o diferenţă între referinţe şi pointeri

  36. void add_3(int *x) { _asm { mov eax,x add dword ptr [eax],3 } } void add_3(int &x) { _asm { mov eax,x add dword ptr [eax],3 } } Referinţe vs. pointeri (2)

  37. Pointeri dubli • un pointer conţine adresa unei variabile • această variabilă poate fi la rândul său un pointer • ş.a.m.d. (foarte rar) • trebuie multă atenţie la tratarea lor

  38. Exemplu • o funcţie pentru inserarea unui element într-o listă înlănţuită • parametru - capul listei • ce tip are? • pointer • dar dacă elementul trebuie inserat înainte de primul din listă? • modificăm capul listei - ne trebuie adresa sa

  39. Mai des decât credem • în limbajul de asamblare, pointerii dubli apar frecvent void f(int *x) mov eax,[ebp+8] // [ebp+8] - pointer dublu mov dword ptr [eax],5 // *x=5; • eroare comună mov dword ptr [ebp+8],5

More Related