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: 2697
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. 2024 )