CURS 7vasile.chis/cursuri/info/c07ppt.pdfCURS 7 Pointeri - tipuri speciale de variabile sau...

21
CURS 7 Pointeri - tipuri speciale de variabile sau constante care au ca valori adrese ale unor alte variabile, constante, functii, structuri de date (adrese ale unor locaţii de memorie) - permit calcule cu adrese - specifice limbajelor de asamblare - sunt folosiţi în scopul scrierii unor programe mai eficiente atât din punctul de vedere al timpului de execuţie cât şi din punctul de vedere al utilizării resurselor hard, în mod concret al utilizării memoriei computerelor. - sunt în mod special utili la alocarea dinamică a memoriei şi la apelul prin referinţă.

Transcript of CURS 7vasile.chis/cursuri/info/c07ppt.pdfCURS 7 Pointeri - tipuri speciale de variabile sau...

Page 1: CURS 7vasile.chis/cursuri/info/c07ppt.pdfCURS 7 Pointeri - tipuri speciale de variabile sau constante care au ca valori adrese ale unor alte variabile, constante, functii, structuri

CURS 7

Pointeri - tipuri speciale de variabile sau constante care au ca valori adrese ale unor alte variabile,

constante, functii, structuri de date (adrese ale unor locaţii de memorie)

- permit calcule cu adrese

- specifice limbajelor de asamblare

- sunt folosiţi în scopul scrierii unor programe mai eficiente atât din punctul de vedere al timpului de execuţie cât şi din punctul de vedere al utilizării resurselor hard, în mod concret al utilizării memoriei computerelor.

- sunt în mod special utili la alocarea dinamică a memoriei şi la apelul prin referinţă.

Page 2: CURS 7vasile.chis/cursuri/info/c07ppt.pdfCURS 7 Pointeri - tipuri speciale de variabile sau constante care au ca valori adrese ale unor alte variabile, constante, functii, structuri

Pointerii - păstrează adresa începutului locaţiei în care este stocată o anumită valoare. - pachet compus din două părţi:

- pointerul însuşi - care are ca valoare adresa primului octet al locaţiei de memorie în care este

stocată o variabilă (sau constantă) - tipul valorii stocate în locaţia de memorie la începutul căreia pointează

- spune computerului câtă memorie să citească după adresa la care pointează şi cum să o interpreteze

Page 3: CURS 7vasile.chis/cursuri/info/c07ppt.pdfCURS 7 Pointeri - tipuri speciale de variabile sau constante care au ca valori adrese ale unor alte variabile, constante, functii, structuri

a) pentru a crea structuri dinamice de date construite din blocuri de memorie b) pentru a opera cu parametrii pasaţi funcţiilor la apelul acestora c) pentru a accesa informaţia stocată în tablouri

Limbajul C foloseşte pointerii în trei moduri:

În cazul unui pointer la o funcţie, tipul pointerului va fi tipul de dată returnat de către funcţie, iar valoarea sa va fi adresa la care începe codul funcţiei respective

Pentru lucrul cu pointeri, limbajul C oferă doi operatori: &

- &x înseamnă adresa variabilei x (de fapt adresa primului octet al locaţiei de memorie în care este stocată variabila x)

* - *p1 valoarea stocată în locaţie de memorie la care pointează pointerul p1.

Page 4: CURS 7vasile.chis/cursuri/info/c07ppt.pdfCURS 7 Pointeri - tipuri speciale de variabile sau constante care au ca valori adrese ale unor alte variabile, constante, functii, structuri

Declararea şi iniţializarea pointerilor

tip *nume_pointer; sau tip* nume_pointer; tip - tip de date de bază sau tip utilizator nume_pointer - identificator folosit pentru pointerul care se declară

Declarare

float *pf; //pf poate conţine adrese la care se află memorate date de tip float

int *pi; //pi poate conţine adrese la care se află memorate date de tip int

char* pc; //pc poate conţine adrese la care se află memorate date de tip char

struct agenda

{

char nume[20];

char tel[15];

};

struct agenda *psa;

//psa este un pointer la date de tip structură agenda.

Exemple

Page 5: CURS 7vasile.chis/cursuri/info/c07ppt.pdfCURS 7 Pointeri - tipuri speciale de variabile sau constante care au ca valori adrese ale unor alte variabile, constante, functii, structuri

double a, *pd;

a=8.406;

pd=&a;

Exemple

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

int *pi; // pi este un pointer la tipul întreg

pi = &n; // pi pointează acum la n

m = *pi; // m are valoarea de la adresa lui n, adică 1

*pi = 0; // n are acum valoarea 0

pi = &s[0]; // pi pointează acum la s[0], adică are ca

// valoare adresa elementului s[0]

*pi=5*m; // s[0] are acum valoarea 5*1=5

float pi, *p;

p=π

*p=3.14159; // se atribuie lui pi valoarea 3.14159

int* p1, p2, p3; //numai p1 este pointer

float *pf1, fact(int *); // se declară pointerul pf1 la tipul float şi o funcţie fact care

returnează o valoare de tip float şi care are ca argument un pointer la tipul int.

Un pointer este constrâns să pointeze la un anumit tip de date!!!

Iniţializare

- precizarea adresei unui obiect definit în memorie. - p - numele unui pointer => *p reprezintă valoarea de la adresa la care "pointează"

pointerul p.

Page 6: CURS 7vasile.chis/cursuri/info/c07ppt.pdfCURS 7 Pointeri - tipuri speciale de variabile sau constante care au ca valori adrese ale unor alte variabile, constante, functii, structuri

Program exemplu

#include <stdio.h>

#include <math.h>

int 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);

return 0;

}

Atenţie la iniţializarea pointerilor !!! + referinta nevalida + pointeri nuli

Exemplu //testare pointer

int* pi=0;

...

if(pi!=0)

n=*pi; //se foloseşte pointerul dacă pointează la o adresă legală (validă)

Page 7: CURS 7vasile.chis/cursuri/info/c07ppt.pdfCURS 7 Pointeri - tipuri speciale de variabile sau constante care au ca valori adrese ale unor alte variabile, constante, functii, structuri

#include <stdio.h>

#include <math.h>

void main()

{

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

}

Page 8: CURS 7vasile.chis/cursuri/info/c07ppt.pdfCURS 7 Pointeri - tipuri speciale de variabile sau constante care au ca valori adrese ale unor alte variabile, constante, functii, structuri

Operaţii cu pointeri

a) Incrementare şi decrementare

Fie declaraţia: int *p;

Instrucţiunile: ++p; şi p++;

respectiv: --p; şi p--;

măresc, respectiv micşorează valoarea lui p cu o unitate (4 octeti)

b) Adunarea şi scăderea unui întreg dintr-un pointer

Rezultatul operaţiei p+n, unde p este un pointer şi n este un întreg este: p+n·r, unde r reprezintă numărul de octeţi folosiţi pentru păstrarea în memorie a datelor de tipul celor spre care pointează p.

Exemplu Fie declaraţiile: int n,*pin=&n;

float x,*pre=&x;

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.

Page 9: CURS 7vasile.chis/cursuri/info/c07ppt.pdfCURS 7 Pointeri - tipuri speciale de variabile sau constante care au ca valori adrese ale unor alte variabile, constante, functii, structuri

c) Scăderea pointerilor int num , *ptr1 ,*ptr2 ;

num=ptr1-ptr2; // rezultatul este un intreg, egal cu numarul de obiecte (locatii de memorie) dintre valorile pointerilor

d) Compararea pointerilor

Comparaţiile logice !=, ==, <, <=, >, >= sunt valabile şi în cazul pointerilor.

Exemplu // functie pentru determinarea lungimii unui sir de caractere

int lsir(char *pc)

{

int i;

for(i=0;*pc!=NULL;pc++)

i++;

return i;

}

int main() { char sir[50]; gets(sir); printf(“Lungimea sirului este %d”,lsir(sir)); return 0; }

Adunarea pointerilor nu este permisa!!! pmed=(pin+pfin)/2; // Invalid pointer addition pmed=pin+(pfin-pin)/2; este o instructiune corecta (la pin se adauga un intreg)

Page 10: CURS 7vasile.chis/cursuri/info/c07ppt.pdfCURS 7 Pointeri - tipuri speciale de variabile sau constante care au ca valori adrese ale unor alte variabile, constante, functii, structuri

Pointeri şi tablouri Pointerii sunt intim legaţi de tablouri - numele unui tablou este un pointer constant care are ca valoare adresa elementului de index 0 al tabloului respectiv. - orice operaţie care se face folosind indicii tablourilor poate fi făcută, chiar mai rapid, prin folosirea pointerilor.

Exemple 1. char text[10]="Anul1Fizica", *pc;

pc=text;

putchar(*pc); //se va tipări caracterul A

pc+=4;

putchar(*pc); //se va tipări caracterul 1

2. char sir[10]=“DevC++";

char *p;

p=sir;

while(*p)

putchar(*p++); //se va tipări sirul “DevC++”

3. double a[15],t;

t=*(a+3); //este echivalent cu t=a[3];

Page 11: CURS 7vasile.chis/cursuri/info/c07ppt.pdfCURS 7 Pointeri - tipuri speciale de variabile sau constante care au ca valori adrese ale unor alte variabile, constante, functii, structuri

Program exemplu: adunarea elementelor unui şir folosind pointeri #include <stdio.h>

#include <conio.h>

#include <stdlib.h>

#include <math.h>

int main()

{

float x[100], *y,v;

double s=0.0,med;

int i;

//genereaza aleator elementele sirului x

for(i=0;i<100;i++)

{

v=rand()/pow(2,15);

x[i]=1000*v-500;

//printf("%5.3f\t",x[i]);

}

//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);

getche();

return 0;

}

Page 12: CURS 7vasile.chis/cursuri/info/c07ppt.pdfCURS 7 Pointeri - tipuri speciale de variabile sau constante care au ca valori adrese ale unor alte variabile, constante, functii, structuri

fără 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;

Exemplu Iniţializarea elementelor unui tablou fără pointeri şi cu pointeri

În primul caz, pentru aflarea adresei elementului x[i] compilatorul generează un cod care înmulţeşte pe i cu dimensiunea unui element al tabloului. În al doilea caz (varianta cu pointeri), compilatorul evaluează o singură dată indicele şirului, salvând astfel 49 de operaţii de multiplicare.

Referirea la elementul unui tablou sub forma a[i] este identică cu *(a+i). a[i]*(a+i) Construcţiile &a[i] şi a+i sunt de asemenea identice. &a[i] a+i

Echivalenţa v[2] cu *(v+2)

Page 13: CURS 7vasile.chis/cursuri/info/c07ppt.pdfCURS 7 Pointeri - tipuri speciale de variabile sau constante care au ca valori adrese ale unor alte variabile, constante, functii, structuri

Apelul prin referinţă utilizând parametri de tip pointer

Apelul funcţiilor prin valoare funcţiei i se transmite valoarea argumentului

Apel: f(x) Antet: void f(int x)

void printsir(float sir[], int dim)

{

int i;

for (i=0; i<dim; i++)

printf("%f\n",sir[i]);

}

prin referinţă funcţiei i se transmite adresa argumentului

Apel: g(&x) Antet: void g(int *pi)

void printsir(float *p, int dim)

{

int i;

for (i=0; i<dim; i++)

printf("%f\n",*p++);

}

Page 14: CURS 7vasile.chis/cursuri/info/c07ppt.pdfCURS 7 Pointeri - tipuri speciale de variabile sau constante care au ca valori adrese ale unor alte variabile, constante, functii, structuri

Program exemplu: ordonarea unui şir folosind pointeri şi funcţie 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;

}

int 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);

return 0;

}

Page 15: CURS 7vasile.chis/cursuri/info/c07ppt.pdfCURS 7 Pointeri - tipuri speciale de variabile sau constante care au ca valori adrese ale unor alte variabile, constante, functii, structuri

Program exemplu: funcţii 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;

}

void sc2(double *i, double *j)

{

double t;

t=*i;*i=*j;*j=t;

}

int 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);

return 0;

}

sc1 nu interschimbă valorile variabilelor din funcţia apelantă ci numai copii ale acestora! sc2 schimba valorile variabilelor din functia apelanta.

Page 16: CURS 7vasile.chis/cursuri/info/c07ppt.pdfCURS 7 Pointeri - tipuri speciale de variabile sau constante care au ca valori adrese ale unor alte variabile, constante, functii, structuri

Tema Să se scrie o funcţie care să returneze 1 dacă se citeşte un număr de la tastatură şi să

returneze 0 în caz contrar. Vezi funcţia getint din B.W. Kernighan and D.M. Ritchie, The C

Programming Language, pag. 81

Pointeri la funcţii

-numele unei funcţii este un pointer la funcţia respectivă -numele funcţiei este o reprezentare în mod intern a adresei la care începe codul funcţiei

- se utilizează pentru transmiterea funcţiilor ca parametri ai altor funcţii.

Exemplu Dacă dorim ca funcţia f să apeleze funcţia g sub forma f(g), funcţia g având antetul: float g(int x)

atunci antetul lui f trebuie să fie de forma: double f (float (*) (int))

Page 17: CURS 7vasile.chis/cursuri/info/c07ppt.pdfCURS 7 Pointeri - tipuri speciale de variabile sau constante care au ca valori adrese ale unor alte variabile, constante, functii, structuri

Exemplu

//Funcţia bisect are ca parametru o altă funcţie f

//======================= Functia f =========================

double f(double x)

{

return x-sqrt(2);

}

//======================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);

Page 18: CURS 7vasile.chis/cursuri/info/c07ppt.pdfCURS 7 Pointeri - tipuri speciale de variabile sau constante care au ca valori adrese ale unor alte variabile, constante, functii, structuri

Structuri de date dinamice în C

- structuri care îşi modifică dimensiunea prin alocarea şi eliberarea (dealocarea) memoriei dintr-o zonă specială de memorie numită "heap“ - permit programatorului să controleze exact consumul de memorie al unui program. - managementul structurilor dinamice se face folosind pointeri

=> o utilizare eficientă a memoriei

Memoria heap este o zonă aparte de memorie corespunzătoare unui program, folosită pentru crearea şi distrugerea structurilor de date care au timp de viaţă limitat.

Memoria heap - zonă de memorie complet separată, controlată de către un manager de memorie de tip "run-time", care face managementul memoriei în timpul execuţiei programului. - este disponibilă programelor de aplicaţii în timpul execuţiei acestora folosind funcţiile malloc şi free.

“read only”

Page 19: CURS 7vasile.chis/cursuri/info/c07ppt.pdfCURS 7 Pointeri - tipuri speciale de variabile sau constante care au ca valori adrese ale unor alte variabile, constante, functii, structuri

Memoria stack (stiva) - regiune speciala de memorie care stocheaza variabilele temporare (locale) create de functii (inclusiv de catre functia main()) - variabilele din memoria “stack” dispar la iesirea din functie - este limitata (dimensiunea ei depinde de sistemul de operare)

=> erori de tipul “stack overflow” - managementul ei este facut de catre CPU (nu necesita managementul programatorului) - acces foarte rapid - “bug”: incercarea de a accesa o variabila locala a unei functii care a iesit din executie, de catre o alta functie.

Memoria heap - variabilele pot fi accesate global, de catre orice functie - managementul ei trebuie facut de catre programator altfel => “memory leak” deoerece memoria alocata de o anumita aplicatie nu va deveni disponibila pentru alte aplicatii - se acceseaza folosind pointeri - nu este limitata d.p.d.v. al numarului de date stocate (evident, e limitata fizic) - accesul este mai putin rapid decat in cazul memoriei “stack” - recomandat sa fie folosita cand se doreste stocarea unui tablou sau a unei structuri de dimensiuni mari

Page 20: CURS 7vasile.chis/cursuri/info/c07ppt.pdfCURS 7 Pointeri - tipuri speciale de variabile sau constante care au ca valori adrese ale unor alte variabile, constante, functii, structuri

Funcţia malloc - prototipul în <stdlib.h> şi în <alloc.h> - alocă o zonă contiguă de memorie şi este de forma: (void *) malloc(dimensiune)

dimensiune - mărimea blocului de memorie alocat în octeţi. - returnează un pointer la primul octet al primei locaţii a blocului de memorie alocat - tipul pointerului se va converti la tipul dorit al datelor care se vor stoca: int *pi,n;

pi=(int *) malloc (n*sizeof(int));

- in caz de eroare, sau daca dimensiune este egală cu zero, returnează pointerul NULL.

Funcţia free - eliberează un bloc de memorie alocat cu funcţia malloc () - apelul acesteia se face cu un parametru care reprezintă pointerul la originea blocului de memorie care se eliberează.

Page 21: CURS 7vasile.chis/cursuri/info/c07ppt.pdfCURS 7 Pointeri - tipuri speciale de variabile sau constante care au ca valori adrese ale unor alte variabile, constante, functii, structuri

Program exemplu: folosirea funcţiilor malloc şi free

//Se aloca dinamic un tablou de n elemente;

#include<stdio.h>

#include<stdlib.h>

int 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);

return 0;

}

Exerciţiu Scrieţi un program care să aloce un bloc de memorie capabil să

stocheze 10 valori de tip long double, să iniţializeze fiecare

dintre aceste valori cu 0.0 şi apoi să elibereze blocul

respectiv de memorie.