Documente online.
Zona de administrare documente. Fisierele tale
Am uitat parola x Creaza cont nou
 HomeExploreaza
upload
Upload




Alocarea dinamica

Informatica




Alocarea dinamica

  1. Pointeri

Memoria interna este împartita în octeti (bytes), fiecare continând 8 biti de informatie. Fiecare octet are o adresa unica.

Un program executabil consta din cod (instructiuni masina corespunzatoare instructiunilor programului C++) si date (variabilele programului C++). Fiecare variabila din program ocupa unul sau mai multi octeti din memorie. Adresa primului octet este adresa variabilei.

Definitie. Un pointer este o adresa. O variabila pointer 434l116e este o variabila capabila sa stocheze adrese.

Declarare

O variabila pointer se declara ca o variabila obisnuita, singura diferenta constând în faptul ca variabila pointer este precedata de asterisc.

Exemplu: int *p;

Declaratia de mai sus ne spune ca variabila pointer p este capabila sa pointeze catre obiecte de tip int.

Operatori de adresare si indirectare

Limbajul C++ pune la dispozitia programatorilor 2 operatori pentru lucrul cu pointeri:

a)     operatorul de adresare &. Daca x este o variabila, atunci &x este adresa lui x în memorie.

b)     operatorul de indirectare *. Se foloseste pentru a accesa obiectul catre care pointeaza un pointer.

Fie declaratia:

int i, *p;

Este crucial sa initializam variabila p înainte de a o utiliza. O metoda este sa-i atribuim adresa unei alte variabile, de exemplu:

p=&i;

Observatie. &i nu este un obiect de tip lvalue (ceea ce înseamna ca nu poate aparea în stânga unei atribuiri), altfel spus, adresa unei variabile statice este constanta.

Observatie. De asemenea, p fiind o variabila pointer, constructia &p este corecta si nu poate fi lvalue.

Fie urmatoarele linii de cod:

int i, *p;

p=&i;

Consecinta acestora se poate urmari în figura de mai jos

Memoria interna

i

p=&i 

p=&i

&p

Fig. 1

Sa analizam urmatoarele linii de cod

int i=2, *p;

p=&i;

cout<<i; // se afiseaza 2

cout<<*p; // se afiseaza 2

*p=5;

cout<<i; // se afiseaza 5

cout<<*p; // se afiseaza 5

Daca p pointeaza catre valoarea i, atunci *p este un alias pentru i. Dupa cum se vede în fig. 1, *p si i au aceeasi valoare si mai mult, schimbarea valorii *p schimba si valoarea i.

Atentie!!! Nu se aplica operatorul de indirectare unei variabile pointer neinitializate, asa cum s-a procedat în exemplul de mai jos

int *p;

*p=1;

Pot aparea erori deoarece p poate pointa catre orice adresa de memorie, ca urmare se modifica o locatie necunoscuta. Locatia modificata poate fi a programului (putând cauza functionarea eronata a acestuia) sau a sistemului de operare (putând cauza o cadere a sistemului).

Atribuirea pointerilor

Limbajul C++ accepta folosirea operatorului de atribuire pentru a copia pointeri. Liniile de cod de mai jos ilustreaza acest aspect. Atentie însa a nu se confunda p=q cu *p=*q.

int i=1, j=3, *p, *q;

p=&i;

q=p; // în acest moment p si q pointeaza catre valoarea i

*p=2;

cout<<i; // se afiseza 2

cout<<*p; // se afiseza 2

cout<<*q; // se afiseza 2

q=&j;

cout<<*q; // se afiseza 3

*q=*p; // se modifica doar valoarea de la adresa q

*p=1;

cout<<i; // se afiseza 1

cout<<*p; // se afiseza 1

cout<<*q; // se afiseza 2

Alocarea memoriei

O a doua metoda de initializare a unei variabile pointer consta în alocarea dinamica a memoriei folosind operatorul new, a carui sintaxa este prezentata mai jos

tip *p;

p = new tip [n];

Efectul instructiunii de mai sus este încercarea de a aloca o zona de memorie continua suficienta pentru a memora n valori de tipul tip. Variabila pointer p va fi initializata cu adresa primului octet al zonei de memorie, în cazul în care operatia reuseste sau cu NULL în caz contrar. Se impune deci, ca înainte de a folosi variabila p sa testam rezultatul încercarii de a aloca memorie.



Observatie. Clauza [n] este optionala. În cazul în care lipseste se considera n

Eliberarea memoriei

Eliberarea memoriei alocata dinamic se face fie utilizând operatorul delete, fie la terminarea programului.

Pointerii si vectorii. Aritmetica pointerilor

O variabila pointer poate pointa catre un element al unui vector. Acest fapt este interesant deoarece folosind aritmetica pointerilor putem accesa si celelalte elemente ale vectorului.

Pentru exemplele de mai jos vom considera declaratia

int a[10], *p, *q, i, j;

Limbajul C++ suporta urmatoarele forme ale aritmeticii pointerilor

a)     Adunarea unui întreg la o variabila pointer

Adunând o valoare j la o variabila pointer p, rezulta un pointer la elementul aflat la j pozitii dupa elementul catre care pointeaza p. Mai exact, daca p pointeaza catre a[i], atunci p+j va pointa catre a[i+j] (daca a[i+j] exista).

Observatie. Trebuie sa ne asiguram ca pointerul rezultat reprezinta o adresa valida.

Observatie. La nivel de octet se adauga j*sizeof(*p) octeti pentru a asigura mutarea peste j elemente.

b)    Scaderea unui întreg dintr-o variabila pointer

Similar ca la adunare cu observatia ca mutarea se face în sens invers. Deci, daca p pointeaza catre a[i], p-j va pointa catre a[i-j]. si în acest caz trebuie sa ne asiguram ca adresa rezultata este valida.

c)     Diferenta a 2 pointeri

Rezultatul întors este distanta în elemente (nu în octeti) între cele 2 adrese. De exemplu, daca p pointeaza catre a[i] si q catre a[j], atunci p-q=i-j si q-p=j-i.

Compararea a 2 pointeri

Se pot folosi operatorii relationali <, <=, >=, >, ==, !=. Rezultatul compararii depinde de pozitia relativa în vector. Ca si diferenta a 2 pointeri, compararea a 2 pointeri are sens când ambii pointeaza catre elemente din acelasi vector.

Pentru a testa cele enuntate mai sus, vom scrie câte un program pentru a determina suma celor n elemente ale unui vector atât în varianta clasica cu vectori cât si în varianta cu pointeri

int a[10], n, i, s=0;

cin>>n;

for(i=0; i<n; i++) cin>>a[i];

for(i=0; i<n; i++) s+=a[i];

cout<<s;

int a[10], n, *p, s=0;

cin>>n;

for(p=a; p<a+n; p++) cin>>*p;

for(p=a; p<a+n; ) s+=*p++;

cout<<s;

În tabelul de mai jos, vom evidentia semnificatia diferitelor variante în care apar operatorii si ++ (semnificatii valabile si pentru cazul --, operatorul * are prioritate mai mare decât si

Expresia

Semnificatia

*p++ sau *(p++)

Valoarea expresiei este *p înainte de incrementare, dupa care se incrementeaza p

(*p)++

Valoarea expresiei este *p înainte de incrementare, dupa care se incrementeaza *p

*++p sau *(++p)

Incrementeaza p, valoarea expresiei este *p dupa incrementare

++*p sau ++(*p)

Incrementeaza p, valoarea expresiei este *p dupa incrementare

Folosirea numelui vectorilor ca pointer

Mai exista o legatura între vectori si pointeri si anume numele unui vector poate fi folosit ca un pointer catre primul element din vector

Exemplu

int a

*a=1; // memoreaza valoarea 1 în a

*(a+1)=2; // memoreaza valoarea 2 în a

În general, a+i este echivalent cu &a[i] si *(a+i) este echivalent cu a[i].

Având în vedere aceste echivalente si pastrând vie în memorie proprietatea adunarii de comutativitate, rezulta o consecinta interesanta si anume a[i] este echivalent cu i[a]

Demonstratie

a[i]=*(a+i)=*(i+a)=i[a]




Document Info


Accesari: 2737
Apreciat: hand-up

Comenteaza documentul:

Nu esti inregistrat
Trebuie sa fii utilizator inregistrat pentru a putea comenta


Creaza cont nou

A fost util?

Daca documentul a fost util si crezi ca merita
sa adaugi un link catre el la tine in site


in pagina web a site-ului tau.




eCoduri.com - coduri postale, contabile, CAEN sau bancare

Politica de confidentialitate | Termenii si conditii de utilizare




Copyright © Contact (SCRIGROUP Int. 2025 )