POINTERI
Un pointer este o variabilă care are ca valori adrese. Pointerii se folosesc pentru a face referire la date cunoscute prin adresele lor. Astfel, dacă p este o variabilă de tip pointer care are ca valoare adresa zonei de memorie alocată pentru variabila întreagă x atunci construcţia *p reprezintă chiar valoarea variabilei x.
În construcţia de mai sus, *p, caracterul * se consideră ca fiind un operator unar care furnizează valoarea din zona de memorie a cărei adresă este conţinută în p. Operatorul unar * are aceeaşi prioritate ca şi ceilalţi operatori unari din limbajul C.
Dacă p conţine adresa zonei de memorie alocată variabilei x, vom spune că p pointează spre x sau că p conţine adresa lui x.
Pentru a atribui unui pointer adresa unei variabile, putem folosi operatorul unar &. Astfel, dacă dorim ca p să pointeze spre x, putem utiliza construcţia:
p = &x;
În limba română se utilizează şi alte denumiri pentru noţiunea de pointer: referinţă, localizator; reper; indicator de adresă.
DECLARAŢIA DE POINTER
Un pointer se declară ca orice variabilă cu deosebirea că numele pointerului este precedat de caracterul *. Astfel, dacă, de exemplu, dorim să declarăm variabila p utilizată anterior pentru a păstra adresa variabilei întregi x, vom folosi declaraţia următoare:
int *p;
Tipul int stabileşte în acest caz faptul că p conţine adrese de zone de memorie alocate datelor de tip int. Declaraţia lui p se poate interpreta în felul următor: *p reprezintă conţinutul zonei de memorie spre care pointează p, iar acest conţinut are tipul int.
În general, un pointer se declară prin:
tip *nume;
ceea ce înseamnă că nume este un pointer care pointează spre o zonă de memorie ce conţine o dată de tipul tip.
Comparând declaraţia de pointer anterioară cu una obişnuită:
tip nume;
putem considera că:
tip *
dintr-o declaraţie de pointer reprezintă tip dintr-o declaraţie obişnuită. De aceea, construcţia
tip *
se spune că reprezintă un tip nou, tipul pointer.
Există cazuri în care dorim ca un pointer să fie utilizat cu mai multe tipuri de date. În acest caz, la declararea lui nu dorim să specificăm un tip anume. Aceasta se realizează folosind cuvântul cheie void:
void *nume;
Exemple:
1)
void main (void)
{ int x,y;
int *p;
y=x+10; // aceast² atribuire este echivalenta cu secventa urmatoare
p=&x;
y=*p+100;
x=y; // este echivalenta cu secventa
p=&x;
(*p)++;
}
2) funcţia permutare de mai jos realizează transferul parametrilor prin adresă:
void permutare (int *x, int *y) // x si y sunt pointeri
{ int temp;
temp = *x; // temp ia valoarea ce se afla la adresa continuta in x
*x=*y; // in zona a carei adresa se afla in x se transfera continutul
// zonei a carei adresa se afla in y
*y=temp; // in zona a carei adresa se afla in y se transfera valoarea
// lui temp
}
Apelul funcţiei permutare se face astfel:
permutare (&a, &b);
pentru a schimba valorile lui a cu b.
LEGĂTURA DINTRE POINTERI ŞI TABLOURI
Numele unui tablou este un pointer deoarece el are ca valoare adresa primului său element. Totuşi există o diferenţă între numele unui tablou şi o variabilă de tip pointer, şi anume unui nume de tablou nu i se poate atribui altă adresă. Deci numele unui tablou trebuie considerat ca fiind un pointer constant.
Dacă x este un parametru formal ce corespunde unui parametru efectiv care este un nume de tablou, x poate fi declarat fie ca tablou fie ca pointer spre tipul tabloului.
Exemplu:
Fie funcţia cu antetul următor:
unsigned lungime (char x[ ]);
Să presupunem că această funcţie determină lungimea unui şir de caractere şi se poate apela prin:
l=lungime(tablou);
unde tablou este de tip caracter.
Antetul funcţiei lungime poate fi schimbat în felul următor:
unsigned lungime (char *x);
Cele două declaraţii sunt identice deoarece declaraţia:
char x[ ];
defineşte pe x ca numele unui tablou de tip caracter; dar atunci el este un pointer spre caractere deci se poate declara prin:
char *x;