programare in limbajul c – cursul 11 p ointeri prof. univ. dr. constantin popescu
DESCRIPTION
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. - PowerPoint PPT PresentationTRANSCRIPT
Programare in limbajul C – Cursul 11Pointeri
Prof. 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
00000000
00000011
x
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.
&x reprezinta adresa lui x. (operatorul de adresare &)
Adresa poate fi pasata la o functie:– scanf("%d", &x);
Adresa poate fi stocata intr-o variabila ……
00000000
00000000
00000000
00000011
x
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;
Pointeri 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 ş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; Pointerul ep 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 null este 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;
}