160 likes | 301 Views
Programare in limbajul C – Cursul 11 P ointeri Prof. univ. dr. Constantin Popescu. Agenda. Declararea pointerilor Pointeri şi tablouri Aritmetica pointerilor Scăderea pointerilor C ompararea pointeri lor Pointeri null. Pointeri.
E N D
Programare in limbajul C – Cursul 11PointeriProf. univ. dr. Constantin Popescu
Agenda • Declararea pointerilor • Pointeri şi tablouri • Aritmetica pointerilor • Scăderea pointerilor • Compararea pointerilor • Pointeri null
Pointeri • Cind o variabila este definita, compilatorul aloca o adresa reala de memorie pentru aceasta variabila: • int x; va aloca 4 bytes in memoria principala, care va fi utilizata pentru a stoca o valoare intreaga. • Cind o valoare este asignata la o variabila, valoarea este plasata in memoria ce a fost alocata: • x=3; va stoca intregul 3 pe 4 bytes din memorie. 00000000 00000000 x 00000000 00000011
Pointeri • Cind valoarea unei variabile este utilizata, continutul din memorie este utilizat: • y=x; va citi continutul de 4 bytes din memorie si apoi il va asigna la variabila y. • &xreprezintaadresa lui x. (operatorul de adresare&) • Adresa poate fi pasata la o functie: • scanf("%d", &x); • Adresa poate fi stocata intr-o variabila …… 00000000 00000000 x 00000000 00000011 y
Declararea pointerilor • Declararea unei variabile pointer se face astfel: tip *numepointer; • De exemplu: • int * p1; p1 este o variabila care pointeaza la un intreg, (sau p1 este un pointer intreg) • char *p2; p2 este un pointer la un caracter • unsigned int * p3; p1 = &x; /* Stocheaza adresa lui x in p1 */ scanf("%d", p1); /* sau scanf("%d",&x); */ • O declaraţie pointer simplă se face în felul următor: int *ip; • Declararea (şi iniţializarea) unei variabile i de tip int, şi setarea pointerului ip să pointeze la ea, se face astfel: int i = 5; ip = &i;
Pointeri • Expresia de atribuire ip = &i conţine ambele părţi ale "procesului cu două etape": &i generează un pointer la i şi operatorul de atribuire atribuie noul pointer variabilei ip. Acum, ip "pointează la" i, ceea ce putem ilustra cu următoarea figură: • De exemplu putem scrie o secvenţă de genul: printf("%d\n", *ip); • care va tipări 5, întrucât ip pointează la i şi i are valoarea 5 (momentan). • Putem scrie o instrucţiune de forma: *ip = 7; • ceea ce semnifică "setează valoarea a ceea ce pointează ip la 7". Rezultatul atribuirii *ip=7 este că valoarea lui i se va modifica la 7, iar figura se schimbă în felul următor:
Pointeri • Dacă apelăm funcţia printf("%d\n", *ip) aceasta va tipări 7. • Când scriem *ip = 7, schimbăm valoarea pointată de ip, dar dacă declarăm o altă variabilă j: int j = 3; ip = &j; • am schimbat variabila pointer ip. Figura o modificăm acum astfel: • Dacă declarăm o altă variabilă pointer: int *ip2; • Atunci putem scrie: ip2 = ip; • Acum ip2 pointează aceeaşi zonă ca şi ip; am făcut de fapt o "copie" a săgeţii:
Pointeri • Urmatoarea atribuire face ca ip2 să pointeze aceeaşi zonă ca şi ip (adică va pointa din nou la i). ip2 = ip; • Urmatoarea instrucţiune stochează la locaţia pointată de ip2, o copie a valorii pointate de ip. *ip2 = *ip; • E important să facem distincţie între un pointer şi valoarea pointată de acel pointer. • Variabila ip nu se poate seta la 5 cu o instrucţiune de genul: ip = 5; /* GREŞIT */ • Cifra 5 fiind o constantă de tip int, iar ip fiind un pointer. • Probabil că vrem să setăm valoarea pointată de ip la 5, ceea ce se realizează prin instrucţiunea: *ip = 5;
Exemplu: void min_max(int a, int b, int *min, int *max){ if(a>b){ *max=a; *min=b; } else{ *max=b; *min=a; } } int main() { int x,y; int small,big; printf(“Doi intregi: "); scanf("%d %d", &x, &y); min_max(x,y,&small,&big); printf("%d <= %d", small, big); return 0; } Pointeri
Pointeri şi tablouri • Pointerii nu trebuie în mod obligatoriu să pointeze la variabile simple. • Aceştia pot pointa şi la elementele unui tablou. De exemplu, putem scrie: int *ip; int a[10]; ip = &a[3]; • Ceea ce obţinem este că ip va pointa la al patrulea element al tabloului a (tablourile sunt indexate începând de la zero). • Putem ilustra situaţia în felul următor:
Aritmetica pointerilor • Variabila ip am folosit-o la fel ca în secţiunea precedentă: *ip ne dă valoarea pointată de ip, care în acest caz va fi val. lui a[3]. • Ştim că pointerul ip indică elementul de pe poziţia 3 a tabloului şi atunci putem să adunăm valoarea 1 lui ip: ip + 1 • În C, obţinem un pointer la următorul element al tabloului, în acest caz acesta elementul este a[4]. • Putem atribui noul pointer unei alte var. pointer: ip2 = ip + 1; • Dacă scriem: *ip2 = 4; • Am setat valoarea lui a[4] la 4. Dar nu e necesar să atribuim o nouă valoare pointer unei variabile pointer pentru a o folosi; putem calcula o nouă valoare pointer şi să o folosim imediat: *(ip + 1) = 5; *(ip + 3) = 7; *(ip - 2) = 4;
Scăderea pointerilor şi compararea lor • Este valabilă expresia ip2 - ip1 = 3 • Când facem dif. dintre doi pointeri, atâta timp cât ei pointează în acelaşi tablou, rez. va fi nr. de el. ce separă cei 2 pointeri. • Doi pointeri se pot compara: doi pointeri sunt egali dacă pointează aceeaşi variabilă sau acelaşi element al unui tablou. • Când se testează egalit. sau inegalitatea a doi pointeri aceştia nu trebuie în mod obligatoriu să pointeze în acelaşi tablou. • Fragmentul de cod de mai jos copiază 10 elemente din tabloul array1 în array2, folosind pointeri: int array1[10], array2[10]; int *ip1, *ip2 = &array2[0]; int *ep = &array1[10]; for(ip1 = &array1[0]; ip1 < ep; ip1++) *ip2++ = *ip1; • Pointerulep pointează dincolo de ultimul el. ce se va copia.
Exemplu • Funcţia mystrcmp compară două şiruri de caractere caracter cu caracter: #include <stdio.h> int mystrcmp(char str1[], char str2[]); int main() { char str1[100],str2[100]; printf("Introduceti sirul 1:\n"); gets(str1); printf("Introduceti sirul 2:\n"); gets(str2); printf("Sirurile sunt: %d\n", mystrcmp(str1,str2)); return 0; } int mystrcmp(char str1[], char str2[]) { char *p1=&str1[0],*p2=&str2[0]; while(1) { if(*p1 != *p2) return *p1 - *p2; if(*p1 == '\0' || *p2 == '\0') return 0; p1++; p2++; } }
Pointeri null (1) • Un pointer nulleste o valoare specială pentru care este garantat faptul că nu pointează nicăieri. • Aceasta înseamnă că nici un alt pointer valid la o altă variabilă sau la un element al unui tablou nu va fi egal cu pointerul null. • Pentru a stabili valoarea unui pointer la null se foloseşte constanta predefinită NULL, care este definită în mai multe fişiere header standard printre care: <stdio.h>, <stdlib.h>, <string.h>. • Pentru a iniţializa un pointer la pointerul null se poate folosi o secvenţa de cod: #include <stdio.h> . . . int *ip = NULL; • Pentru a testa egalitatea unui pointer cu valoarea NULL, înainte de a folosi pointerul, putem folosi o secvenţă de genul: if(ip != NULL) printf("%d\n", *ip);
Pointeri null (2) • La pointerul null ne putem referi folosind şi constanta zero • Pentru a seta valoarea pointerilor la null, vom folosi o instrucţiune de genul: int *ip = 0; • De fapt NULL este o macrodefiniţie care de obicei are valoarea, sau textul de substituţie, 0. • Se poate testa un pointer pentru a vedea dacă este diferit de null prin instrucţiunea: if(ip) printf("%d\n", *ip); • Aceasta instrucţiune este echivalentă cu: if(ip != NULL) printf("%d\n", *ip); • Instructiunea if(ip) este echiv. cu if(ip != 0) şi cu if(ip != NULL).
Versiunea functiei strstr #include <stddef.h> char *mystrstr(char input[], char pat[]) { char *start, *p1, *p2; for(start = &input[0]; *start != '\0'; start++) { p1 = pat; p2 = start; while(*p1 != '\0'){ if(*p1 != *p2) break; p1++; p2++; } if(*p1 == '\0')return start; } return NULL; }