Capitolul 5.3. Pointeri si tablouri

Vezi subiectul anterior Vezi subiectul urmator In jos

Capitolul 5.3. Pointeri si tablouri

Mesaj  zooky la data de Mier Mar 18, 2009 1:46 pm

In C, exista o relatie strinsa intre pointeri si tablouri, atit de strinsa incit pointerii si tablourile pot fi tratate simultan. Orice operatie care poate fi rezolvata prin indicierea tablourilor poate fi rezolvata si cu ajutorul pointerilor. Versiunea cu pointeri va fi in general, mai rapida dar, pentru incepatori, mai greu de inteles imediat.

Declaratia

int a[10]

defineste un tablou de dimensiunea 10, care este un bloc de 10 obiecte consecutive numite a[0], a[1], ..., a[9] notatia a[i] desemneaza elementul deci pozitiile, ale tabloului, numarate de la inceputul acestuia. Daca pa este un pointer pe un interg, decalarat ca

int *pa

atunci asignarea

pa = &a[0]

face ca pa sa pointeze pe al "zero-ulea" element al tabloului a; aceasta inseamna ca pa contine adresa lui a[0]. Acum asignarea

x = *pa

va copia continutul lui a[0] in x.

Daca pa pointeaza pe un element oarecare al lui a atunci prin definitie pa+1 pointeaza pe elemmentul urmator si in general pa-i pointeaza cu i elemente inaintea elementului pointat de pa iar pa+i pointeaza cu i elemente dupa elementul pointat de pa. Astfel, daca pa pointeaza pe a[0]

*(pa + 1)

refera continutul lui a[1], pa + i este adresa lui a[i] si *(pa+i) este continutul lui a[i].
Aceste remarci sint adevarate indiferent de tipul varaiabilelor din tabelul a. Definitia "adunarii unitatii la un pointer " si prin extensie, toata aritmetica pointerilor este de fapt calcularea prin lungimea in memorie a obiectului pointat. Astfel, in pa+i i este inmultit cu lungimea obiectelor pe care pointeaza pa inainte de a fi adunate la pa.
Corespondenta intre indexare si aritmetica pointerilor este evident foarte strinsa. De fapt, referinta la un tablou este convertita de catre compilator intr-un pointer pe inceputul tabloului. Efectul este ca numele unui tablou este o expresie pointer.
Aceasta are citeva implicatii utile. Din moment ce numele unui tablou este sinonim cu locatia elementului sau zero, asignarea

pa = &a[0]

poate fi scrisa si

pa = a

Inca si mai surprinzator la prima vedere este faptul ca o referinta la a[i] poate fi scrisa si ca *(a+i). Evaluind pe a[i], C il converteste in *(a+i); cele doua forme sint echivalente. Aplicind operatorul & ambilor termeni ai acestei echivalente, rezulta ca &a[i] este identic cu a+i: a+i adresa elementului al i-lea in tabloul a. Reciproc: daca pa este un pointer el poate fi utilizat in expresii cu un indice pa[i] este identic cu *(pa+i).
Pe scurt orice tablou si exprimare de indice pot fi scrise ca un pointer si offset si orice adresa chiar in aceeasi instructiune.
Trebuie tinut seama de o difernta ce exista intre numele tablou si un pointer. Un pointer este o variabila, astfel ca pa=a si pa++ sint operatii. Dar, un nume de tablou este o constanta, nu o variabila: constructii ca a=pa sau a++ sau p=&a sint interzise. Atunci cind se transmite un nume de tablou unei functii, ceea ce se transmite este locatia de inceput a tabloului. In cadrul functiei apelate acest fapt argument este o variabila ca oricare alta astfel incit un argument nume de tablou este un veritabil pointer, adica o variabila continind o adresa. Ne vom putea folosi de aceasta pentru a scrie o noua versiune a lui strlen, care calculeaza lungimea unui sir.

strlen(s) /* returneaza lungimea sirului s */
char *s
{
int n;
for (n = 0; *s != '0'; s++)
n++;
return(n);
}

Incrementarea lui s este perfect legala deoarece el este o variabila pointer; s++ nu are efect pe sirul de caractere in funca care a apelat-o pe strlen, dar incrementeaza doar copia adresei. Ca parametri formali in definirea unei functii

char s[]

si

char *s;

sint echivalenti; alegerea celui care trebuie scris este determinata in mare parte de expresiile ce vor fi scrise in cadrul functiei. Atunci cind un nume de tablou este transmis unei functii, aceasta poate, dupa necesitati s-o interpreteze ca tablou sau ca pointer si sa-l manipuleze in consecinta. Functia poate efectua chiar ambele tipuri de operatii daca i se pare potrivit si corect.
Este posibila si transmiterea catre o functie doar a unei parti dintr-un tablou prin transmiterea unui pointer pe inceputul subtabloului. De exemplu, daca a este un tablou;

f(&a[2])

si

f(a + 2)

ambele transmit functiei f adresa elementului a[2] deoarece &a[2] si a+2 sint expresii pointer care refera al treilea element al lui a. In cadrul lui f, declarea argumentului poate citi

f(arr)
int arr[];
{
...
}

sau

f(arr)
int *arr;
{
...
}

Astfel, dupa cum a fost conceputa functia f faptul ca argumentul refera de fapt o parte a unui tablou mai mare nu are consecinte.
avatar
zooky
Moderator
Moderator

Numarul mesajelor : 147
Data de inscriere : 15/03/2009
Varsta : 24
Localizare : Cernatesti City

Vezi profilul utilizatorului http://e-learning.forumhit.ro

Sus In jos

Vezi subiectul anterior Vezi subiectul urmator Sus


 
Permisiunile acestui forum:
Nu puteti raspunde la subiectele acestui forum