210 likes | 579 Views
Alocare dinamica a memoriei. Asigura controlul direct, la executie al alocarii de memorie de catre programator prin apelul unor functii specifice, cu prototipurile in <stdlib.h> si <alloc.h> void* malloc(unsigned n); void* calloc(unsigned ne, unsigned dim);
E N D
Alocare dinamica a memoriei. Asigura controlul direct, la executie al alocarii de memorie de catre programator prin apelul unor functii specifice, cu prototipurile in <stdlib.h>si <alloc.h> void* malloc(unsigned n); void* calloc(unsigned ne, unsigned dim); void* realloc(void* p, unsigned n); void free(void* p); În C++, alocarea dinamică se face mai simplu şi maisigur, folosind operatorii new şi delete. Operatorul new permite alocarea de memorie în heap. El se foloseşte într-una din formele:
Alocare dinamica a memoriei. tip *p, *q, *r; //rezerva o zona de sizeof(tip) octeti p=new tip; //acelasi efect cu initializare cu valoarea // expresiei q=new tip(expresie); //rezerva o zona neinitializata de // expint*sizeof(tip) octeti r=new tip[expint]; Eliberarea memoriei alocate se face prin: delete p; //elibereaza memoria alocata pentru tablou delete [] r;
Exemplul 1: #include <stdlib.h> #include <stdio.h> int main() { double *p; int n; scanf(“%d”, &n); p=(double*)malloc(n*sizeof(double)); if(p==NULL) { printf(“cerere neonorata\n”); exit(1); } return 0; }
Exemplul 2 char* strdup(char* s) { char *p; p=(char*)malloc(strlen(s)+1); if(p) strcpy(p, s); return p; }
Exemplul 3 Citiţi de la intrarea standard un şir de caractere de lungime necunoscută într-un vector alocat dinamic. Alocarea de memorie se va face progresiv, în incremente de lungime INC, după citirea a INC caractere se face o realocare.
Exemplul 3: alocare incrementala a unui vector. char *citire() { char *p, *q; int n; unsigned dim=INC; p=q=(char*)malloc(dim); for(n=1; (*p=getchar())!=’\n’ &&*p!=EOF; n++) { if(n%INC==0) { dim+=INC; p=q=realloc(q,dim); p+=n; continue; } p++; } *p=’\0’; return realloc(q,n); }
Pointeri la pointeri int x=10, *px=&x, **ppx=&px; void pschimb(int **pa, int **pb) { int *ptemp; ptemp=*pa; *pa=*pb; *pb=ptemp; } int *px, *py; pschimb(&px, &py);
Tabele de pointeri. Cititi in memorie un fisier text (de exemplu fisierul standard de iesire). Liniile citite vor fi alocate dinamic prin pointeri dintr-un tablou de pointeri. #include <stdio.h> #include <stdlib.h> #define N 100 void afisare(char **tp, int n) { while(n--) printf(“%s\n”,*tp++); }
Tabele de pointeri. int main() { //tabel de pointeri alocat static char *tp[N]; int lg=0; //numar de linii char linie[80]; while(gets(linie)) tp[lg++]=strdup(linie); afisare(tp, lg); return 0; }
Pointeri la funcţii Numele unei funcţii reprezintă adresa de memorie la care începe funcţia. Numele functiei este un pointer la funcţie. Ca şi variabilele, pointerii la functii: • pot primi ca valori funcţii; • pot fi transmişi ca parametrii altor funcţii • pot fi intorşi ca rezultate de către funcţii La declararea unui pointer către o funcţie trebuiesc precizate toate informaţiile despre funcţie, adică: • tipul funcţiei • numărul de parametri • tipul parametrilor tip (*pf)(listă_parametri_formali);
Pointeri la funcţii Apelul unei funcţii prin intermediul unui pointer are forma: • (*pf)(listă_parametri_actuali); sau mai simplu, fără indirectare: • pf(listă_parametri_actuali); De exemplu, iniţializarea unui tablou cu pointeri cu funcţiile matematice uzuale se face prin: • double (*tabfun[])(double) = {sin, cos, tan, exp, log}; Pentru a calcula rădăcina de ordinul 5 din e este suficientă atribuirea: • y = (*tabfun[3])(0.2); În acest mod putem transmite în lista de parametri a unei funcţii – numele altei funcţii
Exemplu: calculul unei integrale definite. Definiţi o funcţie pentru calculul unei integrale definite prin metoda trapezelor,cu un număr fixat n de puncte de diviziune: Folosiţi apoi această funcţie pentru calculul unei integrale definite cu o precizie dată . Această precizie este atinsă în momentul în care diferenţa între două integrale, calculate cu n, respectiv 2n puncte de diviziune este inferioară lui
Calculul unei integrale definite. #include <math.h> double sinxp(); double trapez(double,double,int,double(*)(double)); double a=0.0, b=1.0, eps=1E-6; int N=10; void main(void) { int n=N; double In,I2n,vabs; In=trapez(a,b,n,sinxp); do { n*=2; I2n=trapez(a,b,n,sinxp); if((vabs=In-I2n)<0) vabs=-vabs; In=I2n; } while(vabs > eps); printf(“%6.2lf\n”, I2n); }
Integrala unei functii definite. double trapez(double a,double b,int n,double(*f)(double)) { double h,s; int i; h=(b-a)/n; for(s=0.0,i=1;i<n;i++) s+=(*f)(a+i*h); s+=((*f)(a)+(*f)(b))/2.0; s*=h; return s; } double sinxp(double x) { return sin(x*x); }
Declaratii complexe. O declaratie complexă este o combinaţie de pointeri, tablouri si functii. In acest scop se folosesc atributele: ()– functie [] – tablou * - pointer care pot genera urmatoarele combinatii: * () – funcţie ce returnează un pointer (*)() – pointer la o funcţie * [] - tablou de pointeri (*)[] – pointer la tablou [][] – tablou bidimensional Există şi combinaţii incorecte, provenite din faptul că nu este permisă • declararea unui tablou de funcţii • Declararea unei funcţii ce returnează un tablou
Declaratii complexe. Combinatiile interzise sunt: • ()[] – funcţie ce returnează un tablou • []() – tablou de funcţii • ()() – funcţie ce returnează o funcţie Regula dreapta – stânga: • se incepe cu identificatorul • se caută în dreapta identificatorului un atribut • dacă nu există, se caută în partea stangă • se substituie atributul cu şablonul text corespunzător • se continuă substituţia dreapta-stânga • se opreşte procesul la întâlnirea tipului datei.
Declaratii complexe exemple. int (* a[10]) ( ); • tablou de 10 • pointeri la • funcţii ce returnează int double (*(*pf)())[3][4]; • pointer la • o funcţie ce returnează un pointer • la un tablou cu 3 linii si 4 coloane de double
Declaratii complexe. Pentru creşterea clarităţii, să definim progresiv noi tipuri folosind typedef /*tipul SIR=sir de caractere*/ typedef char *SIR; /*tipul VECTOR=tablou de 10float*/ typedef float VECTOR[10]; /*tipul MATRICE= tablou de 10x10 float*/ typedef float MATRICE[10][10]; /*tipul PFADRD=pointer la functie de argument double si rezultat double */ typedef double (*PFADRD)(double);
Declaratii complexe. SIR s1, s2; VECTOR b, x; MATRICE a; PFADRD pf1;
Tablouri multidimensionale typedef struct nod3{ int n; double *v; } N3; typedef struct nod2{ int n; N3 **pn3; } N2; N2 *alocmat() { N2 n2, *p2=&n2; int i, j, n; scanf("%d", &n); p2->n = n; p2->pn3=(N3**)malloc(n*sizeof(N3*)); for(i=0; i<n; i++) { p2->pn3[i]=(N3*)malloc(sizeof(N3)); scanf("%d", &p2->pn3[i]->n); p2->pn3[i]->v=(double*)malloc(p2->pn3[i]->n* sizeof(double)); } return p2; }