Pointeri si masive
In limbajul C exista o strinsa legatura intre pointeri si masive. Orice operatie care poate fi realizata prin indicarea masivului poate fi de asemenea facuta prin pointeri, care, in plus, conduce si la o accelerare a operatiei. Declaratia:
int a[10];
defineste un masi 545h76f v de dimensiune 10, care reprezinta un bloc de 10 obiecte consecutive numite a[0] a[9]. Notatia a[i] reprezinta al i-lea element al masivului sau elementul din pozitia i , incepind cu primul element. Daca pa este un pointer la un intreg declarat sub forma:
int *pa;
atunci atribuirea:
pa = &a[0];
incarca variabila pa cu adresa primului element al masivului a
Atribuirea:
x = *pa;
copiaza continutul lui a[0] in x
Daca pa indica un element particular al unui masiv a, atunci prin definitie pa+i indica un element cu i pozitii dupa elementul pe care il indica pa, dupa cum pa-i indica un element cu i pozitii inainte de cel pe care indica pa. Astfel, daca variabila pa indica pe a[0] atunci *(pa+i) se refera la continutul lui a[i]
Aceste observatii sint adevarate indiferent de tipul variabilelor din masivul a
Intreaga aritmetica cu pointeri are in vedere faptul ca expresia pa+i inseamna de fapt inmultirea lui i cu lungimea elementului pe care il indica pa si adunarea apoi la pa, obtinindu-se astfel adresa elementului de indice i al masivului.
Corespondenta dintre indexarea intr-un masiv si aritmetica de pointeri este foarte strinsa. De fapt, o referire la un masiv este convertita de compilator intr-un pointer la inceputul masivului. Efectul este ca un nume de masiv este o expresie pointer, deoarece numele unui masiv este identic cu numele elementului de indice zero din masiv.
Atribuirea:
pa = &a[0];
este identica cu:
pa = a;
De asemenea, expresiile a[i] si *(a+i) sint identice. Aplicind operatorul & la ambele parti obtinem &a[i] identic cu a+i. Pe de alta parte, daca pa este un pointer, expresiile pot folosi acest pointer ca un indice: pa[i] este identic cu *(pa+i). Pe scurt orice expresie de masiv si indice poate fi scrisa ca un pointer si un deplasament si invers, chiar in aceeasi instructiune.
Exista insa o singura diferenta intre un nume de masiv si un pointer la inceputul masivului. Un pointer este o variabila, deci pa = a si pa++ sint instructiuni corecte. Dar un nume de masiv este o constanta si deci constructii de forma a = pa a++ sau p = &a sint ilegale.
Cind se transmite unei functii un nume de masiv, ceea ce se transmite de fapt este adresa primului element al masivului. Asadar, un nume de masiv, argument al unei functii, este in realitate un pointer, adica o variabila care contine o adresa. Fie de exemplu functia strlen care calculeaza lungimea sirului s
strlen(char *s)
Incrementarea lui s este legala deoarece s este o variabila pointer. s++ nu afecteaza sirul de caractere din functia care apeleaza pe strlen, ci numai copia adresei sirului din functia strlen
Este posibil sa se transmita unei functii, ca argument, numai o parte a unui masiv, printr-un pointer la inceputul sub-masivului respectiv. De exemplu, daca a este un masiv, atunci:
f(&a[2])
f(a+2)
transmit functiei f adresa elementului a[2], deoarece &a[2] si a+2 sint expresii pointer care, ambele, se refera la al treilea element al masivului a. In cadrul functiei f argumentul se poate declara astfel:
f(int arr[])
sau
f(int *arr)
Declaratiile int arr[] si int *arr sint echivalente, optiunea pentru una din aceste forme depinzind de modul in care vor fi scrise expresiile in interiorul functiei.
|