17 pointeri
-
Upload
serghei-urban -
Category
Education
-
view
49 -
download
2
Transcript of 17 pointeri
17. Pointeri Un pointer este o variabilă a cărei valoare este adresa de memorie a unei
variabile de tip valoare.
Operatorul & returnează adresa unei variabile. Operatorul * este utilizat pentru
a declara o variabilă de tip pointer, dar şi pentru a o de-referenţia. Dacă pointerul
referă o structură, câmpurile (publice) se pot accesa cu *. sau cu ->.
Pentru a împiedica CLR-ul să gestioneze memoria care este accesată direct prin
intermediul pointerilor, operatorii pe pointeri se pot utiliza doar în contexte nesigure;
din acest motiv, cuvântul cheie unsafe trebuie utilizat atât la definirea unei metode ce
utilizează pointeri, cât şi la apelul acesteia. Suplimentar, trebuie utilizată opţiunea de
compilare /unsafe. using System; namespace pnoro{ class Aplicatie{ unsafe static void Swap(int* p1, int* p2){ int aux = *p1; *p1 = *p2; *p2 = aux; } public static void Main(){ int i=0; int j=1; unsafe{ Swap(&i,&j);} Console.WriteLine("i={0} \t j={1}", i,j); Console.ReadLine(); } }; } În cursul execuţiei unei aplicaţii se poate declanşa colectorul de resurse, iar
acesta defragmentează memoria heap. Acesta poate conduce la mutarea unor obiecte
dintr-o zonă de memorie într-alta (evident, nu poate fi vorba decât de instanţe ale
tipurilor referinţă, căci instanţele tipurilor valoare sunt alocate pe stivă). Se poate
ajunge astfel la invalidarea unor pointeri. Cuvântul cheie fixed poate fi utilizat doar în
contexte nesigure şi specifică faptul că un obiect nu poate fi mutat la o altă adresă de
memorie în timpul defragmentării heap-ului. Încercarea de a utiliza fixed cu instanţe
ale tipurilor valoare conduce la eroare de compilare.
Observaţie:
Nu se poate obţine adresa unei variabile de tip referinţă, dar se poate obţine
adresa unui câmp de un tip valoare dintr-o instanţă de un tip referinţă!
2
using System; namespace pnoro{ class C{ public int i; public C(int i){this.i=i;} }; class Aplicatie{ unsafe static void Swap(int* p1, int* p2){ int aux = *p1; *p1 = *p2; *p2 = aux; } public static void Main(){ C v1 = new C(10); C v2 = new C(20); unsafe{ fixed (int* p1= &v1.i, p2 = &v2.i){ //obiectele sunt “fixate” doar in interiorul blocului //delimitat de fixed Swap(p1,p2); } } Console.WriteLine("v1.i={0}\tv2.i={1}", v1.i,v2.i); Console.ReadLine(); } }; } Tablourile sunt tipuri referinţă, pentru care se alocă memorie din heap; dacă
componentele tabloului sunt tipuri valoare, numele tabloului este pointer la prima
componentă şi poate fi atribuit unei variabile de tipul pointer corespunzător. Ca şi în
C++, se poate utiliza arimetica pe pointeri pentru a parcurge elementele tabloului;
este însă responsabilitatea programatorului să facă această operaţie sigură (să nu
acceseze elemente dincolo de graniţele tabloului). De asemenea, adresa tabloului
trebui fixată pentru a preveni invalidarea pointerilor de către o operaţie de
defragmentare.
Pentru a evita “fixarea” unui tablou, se poate aloca pe stivă, cu stackalloc, un
bloc de memorie capabil să conţină un număr de elemente de un tip precizat;
elementele nu pot fi iniţializate şi li se atribuie , separat, valori: unsafe{ int* pt = stackalloc int[3]; pt[0] = 10; pt[1] = 20; pt[2] = 30; ... }