Un pointer este o variabil care conine adresa unui Obiect (alt variabil sau funcie). Orice variabil are dou elemente caracteristice: valoarea coninut n variabil; valoarea adresei locaiei de memorie. Adresa locaiei de memorie n care este stocat o variabil se poate obine aplicnd operatorul de adres (operatorul &) naintea numelui variabilei (operaie ntlnit frecvent n cazul apelrii funciei scanf). Operatorul de adres poate fi utilizat pentru obinerea valorii adresei oricrei variabile. int a=18; printf("valoarea lui a este %d \n",a); printf("adresa lui a este %p \n", &a); Un pointer este o variabil care are ca valoare o adres de memorie. Spunem c variabila pointer indic locaia de memorie de la adresa pe care o conine. n C, pointerii se refer la un anumit tip: tipul datelor coninute n locaia de memorie indicat de variabila pointer.
=>O variabil pointer n C este de regul pointer la un anumit tip. Declararea variabilelor pointer se face n felul urmtor: tip * nume_variabila_pointer; variabila nume_variabila_pointer conine adrese de zone de memorie alocate datelor de tipul tip. * semnific faptul c variabila este de tip pointer la tipul respectiv. De exemplu, int *p; defineste o variabil p pointer la ntreg. Variabila p poate conine adrese de locaii n care se memoreaz valori ntregi. Se pot declara si pointeri generici, de tip void * ( tipul datelor indicate de ei nu este cunoscut). Un pointer de tip void reprezint doar o adres de memorie a unui obiect oarecare:
- dimensiunea zonei de memorie indicate si interpretarea informaiei nu sunt definite; - poate aprea n atribuiri, n ambele sensuri, cu pointeri de orice alt tip; - folosind o conversie explicit de tip cu operatorul cast : (tip *), el poate fi convertit la orice alt tip de pointer(pe acelai calculator, toate adresele au aceeai lungime). Ca i n cazul variabilelor de orice tip, si variabilele pointer declarate si neiniializate conin valori aleatoare. Pentru a atribui variabilei p valoarea adresei variabilei x, se foloseste operatorul de adres ntr-o expresie de atribuire de forma: p=&x; n urma acestei operaii, se poate spune c pointerul p indic spre variabila x. Pentru a obine valoarea obiectului indicat de un pointer se utilizeaz operatorul de derefereniere (indirectare) (operatorul *): Dac p este o variabil de tip pointer care are ca valoare adresa locaiei de memorie a variabilei ntregi x (p indic spre x) atunci expresia *p reprezint o valoare ntreag (valoarea variabilei x). int x, *p; x=3; p=&x; pr i nt f ( " %d" , *p) ; *p=5; pr i nt f ( " %d" , x) ; Pentru a indica adres inexistent, se utilizeaz ca valoare a unui pointer, constanta NULL. Variabilele pointer pot fi utilizate n expresii si direct, fr indirectare. int x, *p1, *p2; x=3; p1=&x; p2=p1; / / at r i bui r e de poi nt er i Atribuirea p2=p1; copiaz coninutul lui p1 n p2, deci p2 va fi fcut s indice spre acelai obiect ca i p1. n contextul secvenei, p2 va indica tot spre x. Exemple: int x = 1, y = 2, z[ 10] ; int *i p; / * i p est e un poi nt er l a i nt */ i p = &x; / * i p i ndi ca acumspr e x */ y = *i p; / * y est e acum1 */ *i p = 0; / * x est e acum0 */ i p = &z[ 0] ; / * i p i ndi ca acumspr e z[ 0] */ Dac ip indic spre ntregul x, atunci *ip poate aprea n orice context n care ar putea aprea x, deci *i p = *i p + 10; l incrementeaz pe x cu 10. Operatorii unari * si & au o preceden mai mare dect operatorii aritmetici, n consecin: y =*ip +1 preia obiectul spre care indic ip, l adun cu 1 si atribuie rezultatul lui y, iar *ip +=1 incrementeaz obiectul spre care indic ip, ca i ++*ip i (*ip )++ Operatorii unari precum * si ++ se asociaz de la dreapta la stnga. Pointerii fiind variabile, pot fi folosii fr a fi derefereniai. Dac iq este un alt pointer spre tipul int, iq =ip copiaz coninutul lui ip n iq, fcnd astfel ca iq s indice spre ceea ce indic ip. Operatorul de adres (&) se aplic numai obiectelor din memorie: variabile i elemente de tablou. Orice operaie care poate fi realizat cu ajutorul tablourilor cu indici poate fi de asemenea efectuat cu ajutorul pointerilor. Declaraia int a[ 10] ; definete un tablou de dimensiune 10, adic un bloc de 10 elemente consecutive notate a[0], a[1], ..., a[9]. Dac pa este un pointer spre un ntreg, declarat ca int *pa; atunci atribuirea pa = &a[ 0] ; l seteaz pe pa s indice spre elementul zero al lui a; mai precis, pa conine adresa lui a[0].
Instruciunea x = *pa; va copia coninutul lui a[0] n x. Dac pa indic spre un anumit element de tablou, atunci, prin definiie, pa + 1 indic spre urmtorul element, pa + i indic Spre o locaie aflat la i elemente dup pa, iar pa i indic spre o locaie aflat cu i elemente nainte. Prin definiie, valoarea unei variabile sau expresii de tip tablou este adresa elementului zero al tabloului. pa = &a[ 0] ; poate fi scris pa = a; Fie urmtoarele declaraii: tab un tablou de elemente de tip T si p un pointer la tipul T: T tab[N]; T * p; Cele 3 atribuiri urmtoare sunt echivalente, si au ca efect faptul c p va indica adresa primului element al tabloului tab: p=tab; p=&tab; p=&tab[0]; Atribuirea tab=p; nu este permis. Toate operaiile de manipulare a pointerilor iau n considerare n mod automat dimensiunea obiectului spre care se indic. Operaiile permise cu pointeri sunt: - atribuirea pointerilor de acelasi tip; - adunarea unui pointer cu un ntreg, scderea unui ntreg, compararea a doi pointeri care indic spre elemente ale aceluiasi tablou; - atribuirea valorii zero(NULL) sau compararea cu aceasta. Operatorii unari de incrementare si decrementare se pot aplica asupra variabilelor de tip pointer, n format prefix si postfix. T * p; p++; p--; ++p; --p; Operatorul de incrementare aplicat asupra unui operand de tip pointer la tipul T mreste adresa coninut de operand cu numrul de octei necesar pentru a pstra o dat de tipul T (se adun sizeof(T)): T tab[N], * p; int i; p=&tab[i]; p++; p va contine adresa elementului tab[i+1]; n general, un pointer poate fi iniializat ca orice alt variabil, desi n mod normal singurele valori care au sens sunt zero sau o expresie care implic adresele unor date definite anterior. Constanta zero poate fi atribuit unui pointer si, de asemenea, un pointer poate fi comparat cu constanta zero. Constanta simbolic NULL (definit n <stdio.h>) este folosit de obicei n locul lui zero, ca o modalitate de a indica mai clar c aceasta este o valoare special pentru un pointer. Compararea a doi pointeri Doi pointeri care indic spre elementele aceluiasi tablou pot fi comparai, folosind operatorii de relaie si de egalitate. Dac p si q sunt doi pointeri spre elementele tab[i] respectiv tab[j] ale unui tablou, comparaia p<q este adevarat dac i<j. Diferena a doi pointeri Doi pointeri care indic spre elementele aceluiasi tablou pot fi sczui. Dac p si q sunt doi pointeri spre elementele tab[i] si respectiv tab[i+n], diferena q-p are valoarea egal cu n. Se considera urmatoarele declaratii: int t ab[ 100] , N, *pt r , i ; Urmatoarele instructiuni afiseaza la ecran elemenetele tabloului for(i =0; i <N; i ++) pr i nt f ( " %d " , t ab[ i ] ) ; pt r =&t ab[ 0] ; for( i =0; i <N; i ++) pr i nt f ( " %d " , *( pt r +i ) ) ; for( pt r =t ab; pt r <t ab+N; pt r ++) pr i nt f ( " %d " , *pt r ) ; Instructiunea pr i nt f ( " adr esa val oar ea de pe adr esa\ n" ) ; for( pt r =t ab; pt r <t ab+N; pt r ++) pr i nt f ( " %p %d \ n" , pt r , *pt r ) ; Va afisa adresa de memorie a fiecarui element din tablou urmata de valoare de pe adresa char *pmesaj ; atunci instruciunea pmesaj =acum este timpul; i atribuie lui pmesaj un pointer ctre tabloul de caractere. Exist o deosebire important ntre urmtoarele definiii: char t mesaj [ ] = acumest e t i mpul ; /* un tablou */ char *pmesaj = acumest e t i mpul ; /* un pointer */
- Caracterele din cadrul tabloului pot fi modificate individual, dar t mesaj va indica ntotdeauna ctre acelasi spaiu de stocare. - pmesaj este un pointer iniializat s indice ctre o constant sir; poate fi modificat ulterior astfel nct s indice alt locaie, dar rezultatul este nedefinit dac se modific coninutul sirului.