Documente online.
Zona de administrare documente. Fisierele tale
Am uitat parola x Creaza cont nou
 HomeExploreaza
upload
Upload




Aritmetica adreselor

c


Aritmetica adreselor

Daca p este un pointer, atunci p++ incrementeaza pe p in asa fel
incit t acesta sa pointeze pe elementul urmator indiferent de
tipul obiectelor pointate, iar p+=i incrementeaza pe p pentru
a pointa peste i elemente din locul unde p pointeaza curent.
C este consistent si constant cu aritmetica pointerilor;
pointerii, tablourile si aritmetica adresarii constitue punctul
forte al limbajului. Sa ilustram citeva dintre proprietatile
lui scriind un program pentru alocare de memorie rudimentar (dar
este util in ciuda simplitatii sale exista doua rutine:
alloc(n) returneaza un pointer p pe n pozitii caracter consecu-
tive care poate fi utilizat de catre apelantul lui alloc pentru
alocarea de caractere; free(p) elibereaza memoria facind-o astfel
refolosibila mai tirziu. Rutinele sint "rudimentare" deoarece
apelurile la free trebuie facute in ordine inversa apelurilor
la alloc. Aceasta inseamna ca memoria gestionata de alloc si
free este o stiva sau o lista prelucrabila in regim LIFP. Biblio-
teca standard C este prevazuta in functii analoage care nu
au atit de multe restrictii iar in capitolul 8 vom da, pentru
demonstratie si alte versiuni. Intre timp se vor ivi multe aplica-
tii care au realmente nevoie de canalul alloc pentru a dispensa
mici portiuni de memorie, de lungimi neprevazute la momente nepre-
vazute.
Cea mai simpla implementare este de a scrie alloc pentru
declararea de parti ale unui tablou mare pe care il vom numi
allocbuf. Acest tablou este propriu lui alloc si free. Lucrind cu
pointeri, nu cu indici in tablou nu este necesar ca vreo alta
rutina sa cunoasca numele tabloului, care poate fi declarat
static, adica local fisierului sursa care sustine pe alloc
si free numele tabloului fiind invizibil in afara acestui fisier.
In implementarile practice tabloul poate chiar sa nu aiba nici
un nume el putind fi obtinut prin cererea catre sistemul de opera-
re a unui pointer pe un bloc de memorie fara nume.
O alta informatie necesara este legata de cit anume din
allocbuf a fost folosit. Vom utiliza un pointer pe urmatorul
element liber, numit allocp. Cind este apelat alloc pentru n
caractere, el verifica daca exista suficient loc eliberat in
allocbuf. Daca astfel alloc returneaza valoarea curenta a lui
allocp (adica inceputul blocului liber) atunci aceasta valoare
esteincrementata cu n in asa fel incit allocp sa pointeze pe
inceputul urmatoarei zone libere. Free(p) pune pur si simplu
pe allocp pe p daca p este in interiorul lui allocbuf.

#define NULL 0 /* val pointerului in caz de eroare */
#define ALLOCSIZE 1000 /* lung spatiului disponibil */
static char allocbuf[ALLOCSIZE]; /* memorie pentru alloc*/
static char *allocp = allocbuf; /*memorarea parti libere*/
char *alloc(n) /* pointer de return pe n caractere */
int n;
else /* nu-i destul loc */
return(NULL)
}
free(p) /* zona de memorie libera pointata de p */
char *p;


Citeva explicatii. In general un pointer poate fi initializat
ca orice alta variabila, desi in mod normal singurele valori
semnificative sint NULL sau o expresie care opereaza adrese
ale unor date in prealabil definite, de tip specificat. Declaratia

static char *allocp = allocbuf;

defineste pe allocp ca fiind un pointer pe caractere si il initia-
lizeaza pentru a-l pointa pe allocbuf care este urmatoarea
pozitie libera atunci cind incepe programul. Aceasta stare ar
putea fi scrisa si astfel

static char *allocp = &allocbuf[0];

deoararece numele tabloului este adresa elementului zero.

Testul

if (allocp + n <= allocbuf + ALLOCSIZE)

verifica daca este suficient loc pentru a satisface cererea pt
n caractere. Daca ezista loc, noua valoare a lui allocp va
fi cel mult mai dincolo de sfirsitul lui allocbuf. Daca cererea
poate fi satisfacuta, alloc retur neaza un pointer normal (obser-
vati declaratia functiei). Daca nu, alloc trebuie sa returneze un
semnal care sa semnifice ca nu exista spatiu liber. Limbajul C
garanteaza ca nici un pointer care pointeaza o data valida nu va
contine zero, asa ca valoarea zero returnata poate fi utilizata
ca semnal de eveniment anormal, nu exista spatiu liber. Se scrie
NULL in loc de zero pt a indica mai clar ca aceasta este o valoare
speciala pt un pointer. In general intregii nu pot fi asignati
pointerilor; zero este u caz special.

Teste ca

if (allocp + n <= allocbuf + ALLOCSIZE)

si

if (p >= allocbuf && p < allocbuf + ALLOCSIZE)

releva citeva fatete importante ale aritmeticii pointerilor.
Mai intii ca in unele situatii pointerii pot fi separati. Daca p
si q pointeaza pe elemente ale aceluiasi tablou, relatii ca <, >,
=, etc lucreaza exact.

p < q

este adevarata, de ex, in cazul in care p pointeaza pe un element
anterior elementului pe care pointeaza q. Relatiile c= si != sint
si ele permise. Orice pointer poate fi testat cu NULL. Dar nu
exista nici o sansa in a compara pointeri in tablouri diferite. In
cazul fericit se va obtine un evident nonsens, indiferent de
masina pe care se lucreaza. Mai poate sa apara situatia nefericita
in care codul va merge pe vreo masina esuind "misterios" pe altele
In al doilea rind, tocmai s-a observat ca un pointer si un
interg pot fi adunati sau scazuti. Instructiunea

p + n

desemneaza al n-lea obiect dupa cel pointat curent de p. Acest
lucru este adevarat indiferent de tipul obiectelor pe care p a
fost declarat ca pointer. Compilatorul atunci cind il intilneste
pe n, il delaleaza in functie de lungimea obiectelor pe care
pointeaza p, lungime determinata prin declaratia lui p. De exem-
plu, pe PDP11 factorii de scalare sint 11 pentru char, 2 pentru
int si short, 4 pentru long si float si 8 pentru double.

Este valida si scaderea pointerilor: daca p si q
pointeaza pe elementele aceluiasi tablou, p-q este numarul de
elemente dintre p si q. Acest fapt poate fi utilizat pentru a
scrie o noua versiune a lui strlen.

strlen(s) /* returneaza lungimea sirului */
char *s;


Prin declarare, p este initializat pe s, adica sa pointeze pe
primul caracter din s. In cadrul buclei while este examinat pe
care caracter pina se intilneste /0 care semnifica sfirsitul iar
daca while testeaza numai daca expresia este zero este posibila
omiterea testului expilcit iar astfel de bucle sint scrise adesea

while (*p)
p++;

Deoarece p pointeaza pe caractere, p++ face ca p sa avanseze de
fiecare data pe caracterul urmator, iar p-v da numarul de carac-
tere parcurse, adica lungimea sirului. Aritmetica pointerilor este
consistenta: daca am fi lucrat cu float care ocupa mai multa
memorie decit char, si daca p ar fi un pointer pe float, p++ ar
avansa pe urmatorul float. Astfel, vom putea scrie o alta versiune
a lui alloc care pastreaza sa zicem, float in loc de char,
pur si simplu prin schimbarea lui char in float. in cadrul lui
alloc si free. Toate manipularile de pointeri iau automat in
considerare lungimea obiectului pointat in asa fel incit trebuie
sa nu fie alterat.

Alte operatii in afara celor mentionate deja (adunarea sau
scaderea unui pointer cu un intreg, scaderea sau comapararea a doi
pointeri). Toate celelalte operatii arrrtmetice cu pointeri
sint ilegale. Nu este permisa adunarea, impartirea, deplasarea
logica, sau adunarea unui float sau double la pointer.




Document Info


Accesari: 1148
Apreciat: hand-up

Comenteaza documentul:

Nu esti inregistrat
Trebuie sa fii utilizator inregistrat pentru a putea comenta


Creaza cont nou

A fost util?

Daca documentul a fost util si crezi ca merita
sa adaugi un link catre el la tine in site


in pagina web a site-ului tau.




eCoduri.com - coduri postale, contabile, CAEN sau bancare

Politica de confidentialitate | Termenii si conditii de utilizare




Copyright © Contact (SCRIGROUP Int. 2024 )