UNIX,Linux,Retele,Programare
Homespacer Tutorialespacer Forumspacer Utilizatorispacer Cautarespacer Webmailspacer Director web


Pointeri

Scris de tercot

Am cam ramas in urma cu lectiile din curs. Azi mi-am facut putin timp sa fac o scurta introducere in pointeri. Veti vedea ca este intr-adevar o introducere scurta. Nu am avut suficient timp (si nici dispozitia necesara) sa explic toate aplicatiile pointerilor dar e suficient sa va prindeti despre ce si cum fac pointerii. Deci, here it goes:

Unul termen foarte greu de inteles pentru incepatorii in C este pointerul. Ce este un pointer ? La ce este bun ? De ce sa folosim pointeri cand tot ce fac e sa ne ingreuneze munca ? Incerc sa explic chestia asta mai jos.

Incepem cu prima intrebare, si anume “Ce este un pointer ?”

In lectiile anterioare ati vazut ca exista diferite tipuri de date in C. Exista int si long pentru numere intregi, char pentru caractere, float si double pentru numere reale. Pointerul este un tip nou de data dar care spre deosebire de celelalte tipuri memoreaza doar adrese.
Ce inseamna asta ? Ca sa intelegeti ce inseamna trebuie sa va familiarizati cu cativa termeni intalniti in programare. Cand concepeti un program folositi, bineinteles, variabile. La definirea unei variabile stiti ca e important sa cunoasteti doua lucruri: tipul si numele acesteia. In timpul rularii unui program apare un nou termen de care trebuie tinut cont si anume adresa variabilei. Un pointer este o variabila care tine minte acest al treilea termen, adica adresa unei variabile.


Cum se declara un pointer ?

Inainte de a folosi un pointer trebuie sa stim spre ce fel de resursa va pointa, adica sa stim ce tip de variabila se gaseste la adresa care o memoreaza. In functie de tipul de variabila care se gaseste la adresa respectiva, se declara pointerul. Adica, daca avem nevoie, de exemplu, de un pointer care sa pointeze catre o variabila de tip int il vom declara in felul urmator:

int *pInt;

Dupa cum vedeti un pointer se declara ca si o variabila normala, in cazul nostru de tip int, cu diferenta ca numele variabilei are un asterisc ( * ) in fata ceea ce ne spune ca este un pointer, adica este o variabila care pastreaza o adresa a unei variabile de tip int, nu este o variabila de tip int. Ca o conventie de nume majoritatea programatoril prefera ca atunci cand se creaza un pointer sa i se dea un nume care incepe cu litera p (de la pointer). Astfel de fiecare data cand folositi variabila respectiva va amintit ca e pointer, nu o variabila normala.
Prin analogie va puteti da seama cum se declara pointeri pentru alte tipuri de date:

char *pCh; // un pointer catre un caracter
char *float; // un pointer catre un numar intreg

Ok. E usor de declarat un pointer, dar cum ii spun sa memoreze o adresa ?

Ei, daca tot am declarat un pointer e bine sa si memoreze ceva si ca sa fie util trebuie sa memoreze o adresa. De fapt, asta e primul lucru care trebuie sa-l faceti dupa ce ati declarat un pointer: sa-i dati o valoare, sa-l faceti sa pointeze spre ceva.
Pentru a-i spune unui pointer adresa care trebuie sa o memoreze se foloseste semnul egal ca in atribuirile normale cu diferenta ca inaintea variabilei a carei adrese trebuie memorate se pune semnul ‘&’ care ii spune compilatorului ca acolo NU valoarea variabilei trebuie data ca rvalue, ci adresa acesteia.
OK, am invatat sa asociem o adresa trebuie sa vedem si cum se poate citi (afisa) valoarea care se gaseste la adresa respectiva. Asta se face ca si cum s-ar citi o valoare normala doar ca numele pointerului este prefixat de un asterisc ( * ). Asta spune compilatorului sa NU se citeasca/afiseze continutul pointerului si ceea ce se gaseste la adresa care este tinuta in pointer.
Sa vedem si un exemplu concret care va ajuta sa intelegeti mai bine functionarea pointerilor:

#include <stdio.h>

int main(){
int i; // o variabila de tip int
int *pInt // un pointer catre un int

pInt = &i; // pInt citeste adresa lui i

// afisam valoarea lui i si valoarea spre care pointeaza
// pointerul pInt
printf(”n%d - %dn”,i,*pInt);

}

Rezultatul ar trebui sa fie: 10 - 10
Primul 10 este valoarea atribuita variabilei i. Al doilea 10 este valoarea care se gaseste
la adresa care este memorata de pointerul pInt. Cum pInt memoreaza adresa lui i, *pInt
va fi 10 adica valoarea lui i.

Haideti sa ne mai jucam putin cu pointerii. Incercati urmatorul program:

#include <stdio.h>

int main(){
int i, j;
int *pInt;

i = 5;
j = 2;

pInt = &i;
printf(”n*pInt are valoarea %dn”,*pInt);

pInt = &j;
printf(”n*pInt are valoarea %dn”,*pInt);

}

Dupa ce compilati si rulati codul de mai sus va trebui sa vedeti doua linii. Pe prima linie ne spune ca *pInt are valoarea 5 iar pe cea de-a doua linie afisata ne spune ca *pInt are valoarea 2.
De ce ? Simplu… i ia valoarea 5 si j ia valoarea 2. Inainte de primul printf() pInt memoreaza adresa variabilei i, adica *pInt va afisa valoarea variabilei i care este 5. Inainte de al doilea printf() pInt memoreaza adresa variabilei j iar la afisare pe ecran apare 2, adica valoarea variabilei j la care pointeaza acum pInt.

Haideti sa intram la chestii ceva mai avansate cum ar fi folosirea pointerilor in lucrul cu sirurile de caractere. Daca lucrati cu un singur caracter, utilizarea pointerilor nu se deosebeste de utilizarea lor in numerele intregi. In schimb daca folositi siruri de caractere apare o functionalitate in plus si anume posibilitatea de a incrementa sau decrementa un pointer.
Sa vedem un exemplu:

int main(){
int i;
char sir[] = “abcdefghi”;
char *pChar;

pChar = &sir;

for( i = 0 ; i < strlen(sir) ; i++ )
printf("%c",*(pChar + i));

}

Codul de mai sus declara variabila sir si o initializeaza cu sirul de caractere “abcdefghi”. Mai jos declaram un pointer, pChar, care memoreaza date de tip char. Mai jos punem in pChar adresa sirului de caractere declarat mai sus ( sir ).
Bun, avem un sir de caractere, un pointer catre un sir de caractere… now what ? Afisam sirul de caractere afisand fiecare caracter in parte. Probabil va puneti intrebarea “Cum sa afisam un sir daca pChar pointeaza spre un caracter ?”. Ei bine, intr-adevar pointerul pointeaza spre un caracter dar in cazul sirurilor de caractere, care in memorie sunt reprezentate ca un sir lung de adrese consecutive, pointerul pointeaza catre primul caracter din acel sir. Adica, pChar = &sir s-ar traduce ca “Memoreaza primul caracter din sirul sir.” Dupa cum am spus mai sus, toate caracterele sunt reprezentate ca zone consecutive din memorie iar pointerul il putem incrementa
pentru a afisa continutul de la fiecare zona in parte.
In cazul de fata am preferat sa nu incrementez pointerul si sa-i adaug un numar. Dupa cum vedeti am folosit o bucla for in care i este initializat cu valoarea 0 iar conditia de oprire e ca i sa fie mai mic decat lungimea sirului de caractere. La fiecare iteratie se va afisa caracterul care se gaseste la adresa pointata de pChar la care se adauga valoarea lui i. Ce inseamna asta ? Se va afisa din sir “a i-a” valoare. La prima trecere prin bucla i este 0, deci valoarea afisata va fi pChar + 0, adica va afisa primul caracter din sir pentru ca, dupa cum am spus mai sus, cand unui pointer ii atribuim adresa unui sir de fapt ii dam adresa primului caracter din sir. La a doua iteratie se va afisa valoarea de la adresa pChar + 1, adica de la inceputul sirului se “merge” distanta de 1 caracter si este afisat. La fel si mai departe.

Acelasi lucru putea fi scris si de forma:

int main(){
int i;
char sir[] = “abcdefghi”;
char *pChar;

pChar = &sir;

for( i = 0 ; i < strlen(sir) ; i++ ){
printf("%c",*pChar++);
}

}

Codul de mai sus si codul anterior sunt echivalente cu diferenta ca nu se apeleaza pChar + deplasament cum era in primul caz ci se afiseaza doar pChar care este incrementat dupa fiecare afisare. Observati ca am folosit operatorul de incrementare dupa valoarea variabilei, adica mai intai va fi afisat *pChar si apoi va fi incrementat.

Cam asta ar fi ideea de utilizare a pointerilor. Bineinteles, pointerii sunt mult mai complecsi decat am prezentat eu aici. In randurile de mai sus am facut doar o prezentare scurta a ceea ce se numeste pointer.

Pentru a va obisnui cu pointerii pun mai jos inca un exemplu care e util sa il studiati si sa il intelegeti:

Transmiterea unui pointer ca parametru intr-o functie:

#include <stdio.h>

void afiseaza(int *pInt);

int main(){
int i;

i = 5;

afiseaza(&i);

}

void afiseaza(int *pInt){
printf(”%d”,*pInt);
}

In codul de mai sus se poate vedea cum transmitem ca parametru functiei afiseaza() o adresa in locul unei valori. Cazul de fata este doar exemplificativ si nu are o valoare practica deosebita dar in cadrul unui program complex este o tehnica utila dintr-un motiv simplu: daca valoarea transmisa este foarte mare ( ex. o structura de 10MB ) nu este deloc util sa apelam functia dand ca parametru variabila. In schimb putem transmite doar adresa variabilei care urmeaza a fi prelucrate astfel evitand incarcarea memoriei.

Daca aveti nelamuriri, astept sa le postati aici
© OSHO

Categoria: Programare

 
© 2008 SkullBox, all rights reserved