Sunteți pe pagina 1din 13

Curs 7

Pointeri

Pointeri Pointerii sunt tipuri speciale variabile sau constante care au ca valori adrese ale unor alte variabile sau constante, adic adrese ale unor locaii de memorie. Ei permit calcule cu adrese, calcule care sunt specifice limbajelor de asamblare i sunt folosii n scopul scrierii unor programe mai eficiente att din punctul de vedere al timpului de execuie ct i din punctul de vedere al utilizrii resurselor hard, n mod concret al utilizrii memoriei computerelor. Pointerii sunt n mod special utili la alocarea dinamic a memoriei [Beu99] i la apelul prin referin. Pentru a nelege mai uor pointerii este convenabil ca acetia s fie discutai prin comparaie cu variabilele normale. O variabil "normal" este o locaie de memorie care pstreaz o anumit valoare. Am vzut n capitolele precedente c la declararea unei variabile, acesteia i se aloc un anumit numr de octei, iar referirea la valoarea stocat n acei octei se face prin numele respectivei variabile. La nivel main, respectiva locaie are o adres de memorie. Dac de exemplu, variabila declarat este s de tip float, cei 4 octei care ncep la adresa locaiei respective sunt cunoscui programatorului ca i s i pe aceti 4 octei pot fi stocate valori reale n simpl precizie.

Exemple de locaii de memorie, adrese, pointer

Pointerii nu pstreaz o valoare n sens tradiional ci adresa nceputului locaiei n care este stocat o anumit valoare. Deoarece pointerii pstreaz adrese i nu valori "tradiionale", ei pot fi vzui ca un pachet compus din dou pri: pointerul nsui, care are ca valoare adresa primului octet al locaiei de memorie n care este stocat o variabil (sau constant) i tipul valorii stocate n locaia de memorie la nceputul creia pointeaz. Acest tip spune computerului ct memorie s citeasc dup adresa la care pointeaz i cum s o interpreteze. Limbajul C folosete pointerii n trei moduri: a) pentru a crea structuri dinamice de date construite din blocuri de memorie b) pentru a opera cu parametrii pasai funciilor la apelul acestora c) pentru a accesa informaia stocat n tablouri. In C, exist o legtur intim ntre tablouri i pointeri. n cazul unui pointer la o funcie, tipul pointerului va fi tipul de dat returnat de ctre funcie, iar valoarea sa va fi adresa la care ncepe codul funciei respective. Pentru lucrul cu pointeri, limbajul C ofer doi operatori: & i * care se folosesc n faa numelui unei variabile sau constante. Astfel, &x nseamn adresa variabilei x (de fapt adresa primului octet al locaiei de memorie n care este stocat variabila x), iar *p1 valoarea stocat n locaie de memorie la care pointeaz pointerul p1. Declararea i iniializarea pointerilor Pointerii se declar ca orice variabil, deosebirea constnd doar n faptul c numele lor este precedat de caracterul * care reprezeint operatorul unar de indirectare sau de derefereniere.
1

Curs 7

Pointeri

Pentru iniializarea pointerilor se poate folosi operatorul unar &, numit operator de refereniere i care returneaz adresa argumentului su. Declararea pointerilor se face n modul urmtor: tip *nume_pointer; sau tip* nume_pointer; unde tip este un tip de date de baz sau tip utilizator, iar nume_pointer este un identificator folosit pentru pointerul care se declar.

Exemple 1. float *pf; //pf poate conine adrese la care se afl memorate date de tip float
int *pi; char* pc; 2. struct agenda

//pi poate conine adrese la care se afl memorate date de tip int //pc poate conine adrese la care se afl memorate date de tip char

char nume[20]; char tel[15]; }; struct agenda *psa; //psa este un pointer la date de tip structur agenda. Iniializarea pointerilor const n precizarea adresei unui obiect definit n memorie. Dac p este numele unui pointer, atunci *p reprezint valoarea de la adresa la care "pointeaz" pointerul p.

Exemple
1. double a, *pd; a=8.406; pd=&a;

2. int n=1, m=2, s[10];


int *pi; pi = &n; m = *pi; *pi = 0; pi = &s[0]; *pi=5*m; // // // // // // // pi este un pointer la tipul ntreg pi pointeaz acum la n m are valoarea de la adresa lui n, adic 1 n are acum valoarea 0 pi pointeaz acum la s[0], adic are ca valoare adresa elementului s[0] s[0] are acum valoarea 5*1=5

3. float pi, *p;


p=π *p=3.14159; Prin ultima instruciune i se atribuie de fapt lui pi valoarea 3.14159. La declarea i iniializarea pointerilor constani se va ine cont de faptul c printr-o construcie de forma: const int* pi=&i; se declar un pointer neconstant la o constant ntreag, iar printr-o construcie de forma: int* const pi=&i; se declar un pointer constant la un ntreg.
2

Curs 7

Pointeri

n primul caz pointerul pi poate lua diferite valori n timp ce i va fi o constant. n al doilea caz, ntregul i poate fi modificat prin intermediul pointerului dar nu poate fi modificat pointerul pentru a pointa la altceva. De asemenea, la declararea pointerilor ntr-o singur declaraie se va ine cont de faptul c printr-o declaraie de forma: int* p1, p2, p3; numai p1 este pointer, n timp ce p2 i p3 sunt ntregi. Astfel dac se dorete declararea tuturor celor trei pointeri se poate proceda fie sub forma: int *p1, *p2, *p3; fie sub forma: int* p1; int* p2; int* p3; Prin declaraia urmtoare: float *pf1, fact(int *); se declar pointerul pf1 la tipul float i o funcie fact care returneaz o valoare de tip float i care are ca argument un pointer la tipul int. Un pointer este constrns s pointeze la un anumit tip de date. Astfel, dac a fost declarat un pointer la tipul float, ca i n declaraia de mai sus, atunci el nu va putea avea ca valori adrese ale unor locaii de memorie unde sunt stocate date de tip ntreg.

Program exemplu
#include <stdio.h> #include <math.h> void main() { float a,b; float* p; p = &a; *p=4*atan(1.0); b=2*a; printf("a=%f b=%f",a,b); printf("\nValoarea din locatia de memorie la care pointeaza p este %f \nAdresa lui a: %X", *p, p);

Output-ul acestui program este:

i rezult dup parcurgerea etapelor schiate n figura urmtoare: Dup seciunea de declaraii, variabilele a i b au valori arbitrare, iar pointerul p, nefiind iniializat, poate pointa oriunde. Dup instruciunea p=&a; p va pointa la locaia de memorie rezervat variabilei a i va avea ca valoare adresa primului octet al acestei locaii. Dup instruciunea *p=4*atan(1.0); coninutul locaiei de memorie la care pointeaz p, adic valoarea lui a, va fi de 4 ori arcul al crui tangent este 1 (n radiani), adic 3.141593, iar dup instruciunea b=2*a;, valoarea variabilei b va fi 6.283185.

Curs 7

Pointeri

Exerciiu Analizai output-ul generat de urmtoarea secven de program: int *i; printf("%X\n",i); printf("introduceti o valoare intreaga: "); scanf("%d",i); printf("%d\n",*i); printf("%X\t\n",i); printf("%X",++i); Care este numele variabilei a crei valoare se tiprete n urma celui de-al treilea apel al funciei scanf? O atenie special va fi acordat iniializrii pointerilor deoarece pointerii neiniializai indic adrese nevalide. Astfel, n urma unei declaraii i iniializri de forma: int *p; Etapele execuiei programului precedent *p = 4; pointerul neiniializat p pointeaz la o locaie aleatoare de memorie care poate fi una din zona variabilelor globale sau n spaiul programului obiect sau chiar n zona sistemului de operare. Prin atribuirea *p=4; programul va ncerca s scrie valoarea 4 n locaia arbitrar la care pointeaz p ceea ce poate duce la ieirea din execuie sau la blocarea programului sau chiar la coruperea unor date ale sistemului de operare i blocarea acestuia. Aadar, nainte de dereferenierea pointerilor acetia trebuie s fie iniializai cu adrese valide. O alt eroare care se poate face cu pointerii este o referina nevalid care poate fi produs printr-o atribuire de forma p1=p2;, unde p1 i p2 sunt pointeri, iar p2 este neiniializat. Orice referin la *p1 va produce o referin nevalid. Un alt tip de eroare cu pointeri este referina la pointeri nuli. O astfel de eroare se produce cnd un pointer care pointeaz la zero, respectiv la pointerul NULL este folosit pentru a face referin la un bloc de date. Astfel, dac p este un pointer la tipul ntreg, secvena de cod p = 0; *p = 12; este nevalid deoarece nu exist nici un bloc de date la care s pointeze p. In consecin, ncercarea de a citi sau scrie acel bloc de date conduce la o referin nevalid. Menionm c exist cazuri n care un pointer poate pointa la zero, doar dereferenierea unui astfel de pointer fiind nevalid. Un program poate testa dac un pointer va pointa la o adres legal sau nu.

Exemplu
int* pi=0; ... if(pi!=0) n=*pi; //se folosete pointerul dac pointeaz la o adres legal (valid) n loc de valoarea 0 (zero) se poate folosi macroul NULL, aceast valoare pentru un pointer indicnd de asemenea o adres nevalid. Astfel, exemplul precedent poate fi rescris sub forma:
#include <stdio.h> #include <math.h> void main() {
4

Curs 7

Pointeri

int* pi=NULL; int n; scanf("%d",&n); if(n<10) pi=&n; if(pi) { printf("dublul lui n este %d",2*(*pi)); printf("\nAdresa lui n este %X",pi); } else printf("Adresa nevalida: \\x%X",pi); }

Dou exemple de output ale acestui program sunt:

respectiv:

In exemplele discutate pn acum, am vzut c pointerii por fi iniializai fie prin asignarea valorilor adreselor unor variabile sub forma pi=&i, fie prin asignarea valorii NULL. Pointerii mai pot fi iniializai cu ajutorul funciilor care returneaz un pointer. Vom discuta aceste cazuri n capitolul dedicat managementului fiierelor. Operaii cu pointeri Cu pointeri pot fi efectuate urmtoarele operaii: a) Incrementare i decrementare Fie declaraia: int *p; Instruciunile: ++p; i p++; respectiv: --p; i p--; mresc, respectiv micoreaz valoarea lui p cu o unitate. n acest caz, unitatea este de 2 octei deoarece aceasta este lungimea locaiilor de memorie n care se pstreaz datele de tip int. b) Adunarea i scderea unui ntreg dintr-un pointer Rezultatul operaiei p+n, unde p este un pointer i n este un ntreg este: p+nr, unde r reprezint numrul de octei folosii pentru pstrarea n memorie a datelor de tipul celor spre care pointeaz p. Fie declaraiile: int n,*pin=&n; float x,*pre=&x; atunci, dac pin are valoarea 1BBC, expresia pin+3 va avea valoarea 1BBC+6, adic 1BC2. Dac pre are valoarea 1BB6, atunci expresia pre-5 va avea valoarea 1BB6-20, adic 1BA2. Exerciiu Care dintre valorile tiprite n urma instruciunilor de mai jos poate fi prevzut? int *i,a=2,j;
5

Curs 7

Pointeri

i=&a; printf("%X\n",i); for(j=0;j<9;j++) printf("%d\t",*(i+j)); c) Scderea pointerilor n limbajul C nu este permis adunarea pointerilor dar este permis scderea acestora. Prin scderea a doi pointeri se obine un ntreg care reprezint numrul locaiilor de memorie aflate ntre adresele la care pointeaz cei doi pointeri care se scad. Astfel, o instruciune de forma: pmed=(pin+pfin)/2; va semnala o eroare de forma "Invalid pointer addition", n timp ce instruciunea: pmed=pin+(pfin-pin)/2; este corect deoarece n acest caz, la pin se adun ntregul rezultat din diferena pfin-pin mprit la 2. d) Compararea pointerilor Comparaiile logice !=, ==, <, <=, >, >= sunt valabile i n cazul pointerilor. Mai jos este dat ca exemplu o funcie care determin lungimea unui ir de caractere. Menionm c numele unui tablou, deci i al unui ir, este un pointer constant care are ca valoare adresa primului element al tabloului.

Exemplu
// functie pentru determinarea lungimii unui sir de caractere
int lsir(char *pc) { int i; for(i=0;*pc!=NULL;pc++) i++; return i; } void main() { char sir[50]; gets(sir); printf(Lungimea sirului este %d,lsir(sir)); }

Cnd funcia va fi apelat cu numele unui ir, pointerul pc va avea ca valoare adresa primului caracter al irului. n funcia lsir se incrementeaz i ct timp caracterul la care pointeaz pc este nenul. Dup cum deja se tie, orice ir se ncheie cu caracterul NULL. Pointeri i tablouri Aa cum am mai spus, n limbajul C, pointerii sunt intim legai de tablouri, numele unui tablou fiind chiar un pointer constant care are ca valoare adresa elementului de index 0 al tabloului respectiv. Orice operaie care se face folosind indicii tablourilor poate fi fcut, chiar mai rapid, prin folosirea pointerilor.

Exemple
1. char text[10]="Anul1Fizica", *pc; pc=text; putchar(*pc); //se va tipri caracterul A pc+=4; putchar(*pc); //se va tipri caracterul 1 2. char sir[10]="BorlandC"; char *p; p=sir;
6

Curs 7

Pointeri

while(*p) putchar(*p++); //se va tipri sirul BorlandC 3. double a[15],t; t=*(a+3); //este echivalent cu t=a[3];

Program exemplu: adunarea elementelor unui ir folosind pointeri


#include <stdio.h> #include <math.h> #include <stdlib.h> void main() { float x[100], *y,v; double s=0.0,med; int i; //genereaza aleator elementele sirului x randomize(); for(i=0;i<100;i++) { v=rand()/pow(2,15); x[i]=1000*v-500; } //se aduna elementele sirului x; pointerul y a fost initializat cu adresa //primului element al sirului x for(y=x;y!=&x[100];) s+=*y++; med=s/100; printf("\ns= %lg\tmedia= %lg",s,med);

Programul de mai sus genereaz 100 de valori aleatoare n intervalul [-500,500] dup care calculeaz suma i media acestor valori.

Exemplu

Iniializarea elementelor unui tablou fr pointeri i cu pointeri

fr pointeri:
#define DIM 50 int x[DIM],i; for(i=0;i<DIM;i++) x[i]=0;

cu pointeri:
#define DIM 50 int x[DIM], *pi; for(pi=x;pi<&x[DIM];pi++) *pi=0;

n primul caz, pentru aflarea adresei elementului x[i] compilatorul genereaz un cod care nmulete pe i cu dimensiunea unui element al tabloului. n varianta cu pointeri, compilatorul evalueaz o singur dat indicele irului, salvnd astfel 49 de operaii de multiplicare. Referirea la elementul unui tablou sub forma a[i] este identic cu *(a+i). De fapt, imediat ce se ntlnete o referin de forma a[i], compilatorul C convertete aceasta la *(a+i). Evident, construciile &a[i] i a+i sunt de asemenea identice.

Curs 7

Pointeri

Echivalena v[2] cu *(v+2)

Apelul prin referin utiliznd parametri de tip pointer Apelul funciilor poate fi fcut n dou moduri i anume prin valoare, caz n care funciei i se transmite valoarea argumentului i respectiv prin referin, caz n care funciei i se transmite adresa argumentului. Astfel, un apel de forma: f(x) este un apel prin valoare deoarece funciei f i se transmite valoarea argumentului x, iar un apel de forma: g(&x) este un apel prin referin deoarece funciei g i se transmite adresa variabilei x. Antetele celor dou funcii vor fi de forma: void f(int x) respectiv: void g(int *pi) Un tablou poate fi transferat unei funcii n dou moduri. S presupunem c vrem s construim o funcie care tiprete elementele unui ir la ieirea standard. O versiune a acestei funcii ar putea fi de forma: void printsir(float sir[],int dim) { int i; for (i=0; i<dim; i++) printf("%f\n",sir[i]); } Funciei i s-a transferat tabloul sir i dimensiunea acestuia. O a doua versiune a acestei funcii poate fi de forma: void printsir(float *p,int dim) { int i; for (i=0; i<dim; i++) printf("%f\n",*p++); } n acest caz, funciei i se transfer un pointer i anume tocmai numele tabloului care trebuie tiprit i dimensiunea tabloului.

Curs 7

Pointeri

Program exemplu: ordonarea unui ir folosind pointeri i funcie care returneaz un pointer la irul ordonat
#include <stdio.h> void printsir(float *p, int dim) { int i; for (i=0; i<dim; i++) printf("%f\n",*p++); } float* ordsir(float *p0, int dim) { float *p=p0,t; int k,i; do { k=1; p=p0; while(p<(p0+dim-1)) //p0+dim-1 are ca valoare adresa ultimului element { if(*p<*(p+1)) { t=*p; *p=*(p+1); *(p+1)=t; k=0; } p++; } } while(k==0); return p-dim+1; } void main() { float x[100],*p; int n,i; printf("Dimensiunea sirului: "); scanf("%d",&n); for(i=0;i<n;i++) { printf("x[%d]= ",i); scanf("%f",&x[i]); } p=x; p=ordsir(p,n); printsir(p,n); }

Un alt exemplu n care este necesar ca apelul unei funcii s se fac prin valoare este acela al unei funcii care trebuie s realizeze interschimbarea a dou valori.

Program exemplu: funcii swap cu apel prin valoare i prin referin


#include <stdio.h> void sc1(double v1, double v2) { double t; t=v1;v1=v2;v2=t; }
9

Curs 7

Pointeri

void sc2(double *i, double *j) { double t; t=*i;*i=*j;*j=t; } void main() { double a,b; printf("Adresa la care incepe codul functiei sc1 este: %X\n",sc1); scanf("%lf%lf",&a,&b); sc1(a,b); printf("\nApelul functiei sc1:\na= %lg\tb=%lg",a,b); sc2(&a,&b); printf("\nApelul functiei sc2:\na= %lg\tb=%lg",a,b); }

Un exemplu de output al acestui program este:

Dup cum se vede, funcia sc1 nu interschimb valorile variabilelor din funcia apelant ci numai copii ale acestora. Pe de alt parte, funcia sc2, al crui apel se face prin referin, realizeaz interschimbarea celor dou valori. Aadar, argumentele de tip pointer permit funciilor s acceseze i s modifice valorile variabilelor funciei apelante. Exerciiu S se scrie o funcie care s returneze 1 dac se citete un numr de la tastatur i s returneze 0 n caz contrar. Vezi funcia getint din B.W. Kernighan and D.M. Ritchie, The C Programming Language, pag. 81, http://madison-project.wdfiles.com/local--files/tutorials/The_C_Programming_Language.pdf]. Pointeri la funcii La fel ca i numele unui tablou i numele unei funcii este un pointer la funcia respectiv, adic numele funciei este o reprezentare n mod intern a adresei la care ncepe codul funciei. Pointerii la funcii se utilizeaz pentru transmiterea funciilor ca parametri ai altor funcii. Dac dorim ca funcia f s apeleze funcia g sub forma f(g), funcia g avnd antetul: float g(int x) atunci antetul lui f trebuie s fie de forma: double f (float (*) (int))

Exemplu

Exemplu

//Funcia bisect are ca parametru o alt funcie f //======================= Functia f ========================= double f(double x) { return x-sqrt(2);
10

Curs 7

Pointeri

} //======================Functia bisect ======================= double bisect(double inf, double sup, double (*pf)(double)) { double c,sol; if((*pf)(inf)==0) return inf; if((*pf)(sup)==0) return sup; if((*pf)(inf)*(*pf)(sup)>0) { printf("\n\a\aNu exista sol sau exista sol. multiple"); getch(); exit(1); } do { c=(inf+sup)/2.0; if((*pf)(c)==0) return c; if((*pf)(inf)*(*pf)(c)<0) sup=c; else inf=c; } while(fabs((*pf)(c)) >= eps); return c; } //=================Apelul functiei bisect======================= s=bisect(A,B,f);

Tablouri de pointeri; pointeri la pointeri Deoarece pointerii sunt variabile i ei pot fi stocai n tablouri. Un astfel de tablou de pointeri ar putea fi util la scrierea unui program care s sorteze ntr-o anumit ordine liniile unui text de input (vezi [Ker88], pag.91). Un tablou de pointeri se declar la fel ca orice tablou, diferena constnd n faptul c elementele tabloului sunt pointeri.

Exemple
char *pr[1000]; //tablou cu maxim 1000 de elemente; elementele sunt pointeri la tipul char int *ptr[100]; //tablou cu maxim 100 de elemente; elementele sunt pointeri la tipul int Structuri de date dinamice n C Structurile de date dinamice sunt structuri care i modific dimensiunea prin alocarea i eliberarea (dealocarea) memoriei dintr-o zon special de memorie numit "heap". Acestea sunt extrem de importante n C deoarece permit programatorului s controleze exact consumul de memorie al unui program. Structurile dinamice aloc blocuri de memorie din heap n funcie de necesiti, iar managementul acestor blocuri se face folosind pointeri. Cnd anumite structuri de date nu mai sunt folosite, ele vor returna blocurile corepunztoare memoriei heap, pentru a fi refolosite de ctre orice program, realizndu-se astfel o utilizare eficient a memoriei. Memoria heap este o zon aparte de memorie corespunztoare unui program, folosit pentru crearea i distrugerea structurilor de date care au timp de via limitat. Dup cum este schematizat n Figura 1, conceptual, memoria alocat unui program este mprit n patru segmente: segmentul corespunztor codului executabil, segmentul corespunztor variabilelor globale, segmentul de memorie stiv i segmentul memoriei heap.

11

Curs 7

Pointeri

Fig.1

Segmentul cod conine biii corespunztori instruciunilor programului i acest segment de memorie este determinat de ctre compilator i link-editor. Tot aici sunt incluse funciile de bibliotec ce sunt adugate programului. In general, aceast memorie este de tip "read-only". Segmentul de memorie corespunztor variabilelor globale ale programului, numit i segment de date statice, este folosit pentru stocarea variabilelor globale. Segmentul memoriei stiv pstreaz variabilele locale i parametrii unei funcii. Un cadru stiv este creat la apelul unei funcii i este eliberat la ncetarea execuiei funciei respective. La fiecare apel al unei funcii, variabilele sale locale i parametrii si sunt mpinse n memoria stiv. La ieirea din funcie, aceste variabile i parametri sunt eliminai din stiv. Din aceast cauz, mrimea memoriei stiv a unui program, chiar dac are o valoare maxim, se modific continuu n timpul execuiei programului. Memoria heap este o zon de memorie complet separat, controlat de ctre un manager de memorie de tip "run-time", care face managementul memoriei n timpul execuiei programului. De fapt acest manager de memorie este o funcie de bibliotec adugat programului aflat n execuie. Dac un program folosete structuri dinamice n memoria heap, atunci cnd aceste structuri nu mai sunt folosite, managerul de memorie va marca blocurile de memorie corespunztoare acestora ca fiind libere. Atunci cnd un program de aplicaii i ncheie execuia, sistemul de operare va descrca acel program din memorie, precum i variabilele sale globale i stiva sa, astfel nct un alt program va putea folosi spaiul corespunztor de memorie. n acest fel, memoria computerelor este n permanen reciclat i refolosit de ctre programe pe msur ce acestea se afl n execuie i se ncheie. Memoria heap este disponibil programelor de aplicaii n timpul execuiei acestora folosind funciile malloc i free. Acestea permit ca unui program s i se aloce memorie, pentru o perioad determinat, exact atunci cnd este nevoie n timpul execuiei programului. Funciile malloc i free S presupunem c dorim alocarea unei anumite zone de memorie n timpul execuiei unui program. Acest lucru se face cu ajutorul funciei malloc, care va aloca un bloc de memorie din heap. Sistemul de operare va rezerva acel bloc de memorie pentru program, bloc care va putea fi folosit n orice fel n programul respectiv. Cnd acel bloc nu mai este necesar, el va fi returnat sistemului de operare pentru a fi folosit de ctre alte aplicaii. Eliberarea (dealocarea) unui bloc de memorie se face folosind funcia free. Funcia malloc i are prototipul n <stdlib.h> i n <alloc.h>, aloc o zon contigu de memorie i este de forma: (void *) malloc(dimensiune) unde dimensiune reprezint mrimea blocului de memorie alocat n octei. Funcia returneaz un pointer void, adic un pointer la o zon de tip necunoscut de date. La o iniializare ulterioar pointerul va fi convertit la un pointer specific unui anumit tip de date (vezi exemplul de mai jos).
12

Curs 7

Pointeri

n caz de succes, funcia malloc returneaz un pointer la primul octet al primei locaii a blocului de memorie alocat, iar n caz de eroare returneaz pointerul NULL. Tot pointerul NULL este returnat i cnd dimensiune este egal cu zero. Funcia free elibereaz un bloc de memorie alocat cu funcia malloc i apelul acesteia se face cu un parametru care reprezint pointerul la originea blocului de memorie care se elibereaz. Mai jos este prezentat un program exemplu n care se folosesc funciile malloc i free. Pn acum, cnd am lucrat cu tablouri, acestea au fost declarate de o anumit dimensiune maxim DIM, iar programul putea folosi tablouri avnd maxim DIM elemente. De cele mai multe ori ns, programul cere numrul de elemente al tabloului, n, care este de obicei mai mic dect DIM. n programul exemplu de mai jos, memoria necesar tabloului va fi alocat dup citirea numrului su de elemente i va fi exact ct este necesar.

Program exemplu: folosirea funciilor malloc i free


//Se aloca dinamic un tablou de n elemente; #include<stdio.h> #include<stdlib.h> void main() { int n,i; float *p,*p0; printf("Introduceti dimensiunea tabloului: "); scanf("%d",&n); p=(float *)malloc(n*sizeof(float)); //(float *) converteste pointerul void //returnat de catre malloc intr-un pointer la tipul float p0=p; if (p==NULL) { printf("Eroare: Memorie nedisponibila\n"); exit(1); } for(i=0;i<n;i++) { *p=i; printf("\n%X\t%g",p,*p); p++; } free(p0); }

Un exemplu de output al acestui program este:

Exerciiu Scriei un program care s aloce un bloc de memorie capabil s stocheze 10 valori de tip long double, s iniializeze fiecare dintre aceste valori cu 0.0 i apoi s elibereze blocul respectiv de memorie.
13