Sunteți pe pagina 1din 4

8. Tablouri i pointeri. 8.2. Pointeri.

Un pointer este o variabil care are ca valori adrese ale altor variabile, sau mai general adrese de memorie. Un pointer este asociat unui tip de variabile, deci avem pointeri ctre int, char, float, etc. n general o variabil pointer p ctre tipul T se declar: T *p; Un tip pointer la tipul T are tipul T*. Exemple: int j,*pj; /*pj este o variabila de tip pointer la ntregi*/ char c, *pc;

Se introduc doi noi operatori: operatorul de adresare & - aplicat unei variabile furnizeaz adresa acelei variabile

pj=&j; /* iniializare pointer */ pc=&c; Aceste iniializri pot fi fcute la definirea variabilelor pointeri: int j, *pj=&j; char c, *pc=&c; O greeal frevent comis o reprezint utilizarea unor pointeri neiniializai. int *px; *px=5; /* greit, pointerul px nu este iniializat (legat la o adres de variabil ntreag */

Pentru a evita aceast eroare vom iniializa n mod explicit un pointer la NULL, atunci cnd nu este folosit. operatorul de indirectare (derefereniere) * permite accesul la o variabil prin intermediul unui pointer. Dac p este un pointer de tip T*, atunci *p este obiectul de tip T aflat la adresa p. n mod evident avem: *(&x) = x; &(*p) = p; Exemplu; int *px, x; x=100; px=&x; // px contine adresa lui x printf(%d\n, px); // se afiseaza 100 Dereferenierea unui pointer neiniializat sau avnd valoarea NULL conduce la o eroare la execuie. 8.3. Pointeri void. tip. Pentru a utiliza un pointer cu mai multe tipuri de date, la declararea lui nu l legm de un anumit

void *px; // pointerul px nu este legat de nici un tip Un pointer nelegat de un tip nu poate fi derefereniat. Utilizarea acestui tip presupune conversii explicite de tip (cast). Exemplu: int i; void *p; . . .

p=&i; *(int)p=5; // ar fi fost gresit *p=5 Exemplul 17: Definiti o functie care afiseaza o valoare ce poate aparine unuia din tipurile: char, int, double. #include <stdio.h> enum tip {caracter, intreg, real}; void afisare(void *px, tip t) { switch(t) { case caracter: printf("%c\n", *(char*)px); break; case intreg: printf("%d\n", *(int*)px); break; case real: printf("%lf\n",*(double*)px); break; } } void main(void) { char c='X'; int i=10; double d=2.5; afisare(&c, caracter); afisare(&i, intreg); afisare(&d, real); } 8.4. Pointeri constani i pointeri la constante. In definiiile: const int x=10, *px=&x; x este o constant, n timp ce px este un pointer la o constant. Aceasta nsemn c x, accesibil i prin px nu este modificabil (operaiile x++ i (*px)++ fiind incorecte, dar modificarea pointerului px este permis (px++ este corect). Un pointer constant (nemodificabil), se definete prin: int y, * const py=&y; In acest caz, modificarea pointerului (py++) nu este permis, dar coninutul referit de pointer poate fi modificat ( (*py)++ ). Un pointer constant (nemodificabil) la o constant se definete prin: const int c=5, *const pc=&c; In cazul folosirii unor parametri pointeri, pentru a preveni modificarea coninutului referit de acetia se prefer definirea lor ca pointeri la constante. De exemplu o functie care compar dou iruri de caractere are prototipul: int strcmp(const char *s, const char *d); 8.5. Operaii aritmetice cu pointeri.

Asupra pointerilor pot fi efectuate urmtoarele operaii: adunarea / scderea unei constante incrementarea / decrementarea scderea a doi pointeri de acelai tip

Prin incrementarea unui pointer legat de un tip T, adresa nu este crescut cu 1, ci cu valoarea sizeof(T) care asigur adresarea urmtorului obiect de acelai tip. n mod asemntor, p + n reprezint de fapt p+n*sizeof(T) . Doi pointeri care indic elemente ale aceluiai tablou pot fi comparai prin operatorii de relaie i relaia de egalitate, sau pot fi sczui. Pointerii pot fi comparai prin relaiile == i != cu constanta simbolic NULL (definit n stdio.h). 8.6. Legtura ntre pointeri i tablouri. ntre pointeri i tablouri exist o legtur foarte strns. Orice operaie realizat folosind variabile indexate se poate obine i folosind pointeri. adic, dac x este un tablou (de exemplu int x[10];) atunci x &x[0] n C numele unui tablou este un pointer constant la primul element din tablou: x=&x[0] Numele de tablouri reprezint pointeri constani, deci nu pot fi modificai ca pointerii adevrai. Exemplu: int x[10], *px; px=x; /* sunt operatii permise */ px++; x=px; /* sunt operatii interzise, deoarece x este */ x++; /* pointer constant */ Prin urmare variabilele indexate pot fi transformate n expresii cu pointeri i avem echivalenele: Notaie indexat &x[0] &x[1] &x[i] &x[n-1] Adres Notaie cu pointeri x x+1 x+i x+n-1 Valoare Notaie indexat x[0] x[1] x[i] x[n-1] Notaie cu pointeri *x *(x+1) *(x+i) *(x+n-1)

n C avem urmtoarea echivalen ciudat!:Dac x este un tablou de ntregi x[i] i[x] ntr-adevr: x[i]=*(x+i)=*(i+x)=i[x] 8.7. Parametri tablouri. Dac n lista de parametri a unei funcii apare numele unui tablou cu o singur dimensiune se va transmite adresa de nceput a tabloului. Aceasta ne permite s nu specificm dimensiunea tabloului, att la definirea, ct i la apelul funciei. Exemplul 18: Scriei o funcie care calculeaz produsul scalar a doi vectori x i y, avnd cte n componente fiecare. Antetul funciei va fi: double scalar(int n, double x[], double y[]) Funcia poate fi declarat cu parametri formali pointeri n locul tablourilor: double scalar(int n, double *x, double *y) { double P=0; for (int i=0; i<=n; i++) P=P+x[i]*y[i] return P; }