Sunteți pe pagina 1din 20

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 mai
sigur, 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.
b
I   f(x) dx
a

Definiţi o funcţie pentru calculul unei integrale definite


prin metoda trapezelor,cu un număr fixat n de puncte
de diviziune:

 f(a)  f( b) n 1 ba
b

a f ( x ) dx  h 
 2
 
i 1
f (a  ih ) 

cu h 
n

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;
}