Laborator 1
Pointeri . Operatii cu pointeri
În acest capitol sunt prezentate consideraţii teoretice privind definirea şi utilizarea pointerilor fiind
prezentate câteva probleme rezolvate cu pointeri la date de tip întreg, la tipul caracter şi la şir de
caractere.
CONSIDERAŢII TEORETICE
Variabila de tip pointer este o variabilă care are ca şi valoare o adresă de memorie.
Pointerii se clasifică astfel:
Pointer la date = conţine adresa unei variabile sau a unei constante
Pointer la funcţii = conţine adresa codului executabil al unei funcţii
Pointer la obiecte = conţine adresa unui obiect în memorie = adrese de date şi funcţii
Pointerii conţin adrese de memorie şi nu valori ca alte tipuri de variabile sau constante.
Dacă la o adresă de memorie se află altă adresă acest lucru are semnificaţia de indirectare
(“pointare”) (o variabilă indică spre alta ).
În Fig.1.1 este prezentat un exemplu de adrese de memorie în care sunt memorate date sau alte
adrese ale altor date . Variabila
Adresa
de memorie din memorie
altă adresa de memorie
1000 1003
1001
1002
1003
0001
. . . valoarea unei variabile
1004
Fig.1.1. Reprezentarea variabilelor în memorie
Formatul de declarare al unei variabile de tip pointer este : tip *nume ;
unde tip= tipul de baza al pointerului, defineşte tipul variabilei la care indică acesta;
poate fi orice tip de variabilă;
nume= numele variabilei pointer
Operatorii specifici pointerilor sunt : &, *.
Operatorul de adresare (referentiere): & (“adresa lui”) este un operator unar care asociat unei
variabile sau obiect, returnează adresa de memorie a acelei variabile sau obiect.
Operatorul de indirectare (dereferentiere): * (“de la adresa”) este un operator unar,
complementar lui &, returnează valoarea înregistrata la adresa de memorie specificată.
Observatii:
-1-
Operatorul * nu trebuie confundat cu operatorul aritmetic utilizat pentru înmulţire (*).
Operatorul & nu trebuie confundat cu operatorul AND pentru biţi (&) .
Operatorii * şi & au prioritate faţă de toţi operatorii aritmetici (cu exceptia lui –unar cu care au
aceeasi precedenţă).
După declararea pointerului trebuie specificat către ce anume indică acesta (o alta variabila de tip
data sau un alt pointer) deoarece implicit nu indică nimic.
Ex.1:Instrucţiunile din paragraful INCORECT vor genera eroare , deoarece variabila de tip pointer
nu a fost iniţializată.
INCORECT: CORECT:
int *ip; int *ip, x;
*ip = 100; ip = &x;
*ip = 100;
Ex.2: Un alt exemplu de declarare şi iniţializare de pointer
Prin 2 instrucţiuni distincte:
int a=1, *ptoa;
ptoa = &a; //pointerului ptoa i se atribuie adresa variabilei a
Printr-o singură instrucţiune:
int a=1, *ptoa= &a; //pointerului ptoa i se atribuie adresa variabilei a
Pentru exemplul anterior în Fig.1.2. este reprezentat modul de definire a pointerului *ptoa într-o
zonă de memorie. Adresele de memorie sunt reprezentate prin numere în baza 16 (0x00,…, 0xFF).
Pointerul se numeste *ptoa, este iniţializat cu adresa &a, iar locaţia de memorie care este
rezervată lui *ptoa va conţine numărul 1, adicăvaloarea variabilei a.
… 0001 …
0x00 0xFF
valoarea variabilei a
*ptoa=&a (adresa variabilei a)
Fig.1.2. Reprezentarea unui pointer în memorie prin adresă şi conţinut
Operațiile permise asupra pointerilor sunt:
1. Comparare
2. Iniţializare. Atribuire
3. Adunarea/Scăderea unui nr. întreg la/dintr-un pointer
4. Scăderea a 2 pointeri
5. Incrementare/Decrementare
Operațiile nepermise asupra pointerilor sunt:
Adunarea a 2 sau mai mulţi pointeri
Adunarea/scăderea tipului float sau double la/din pointeri
Înmulţirea a 2 sau mai mulţi pointeri
Împărţirea a 2 sau mai mulţi pointeri
Aplicarea operatorilor pe bit pointerilor
2
[Link] pointerilor se poate realiza în două moduri:
a) Compararea a doi pointeri
Operatorii relaţionali permit compararea a 2 pointeri într-o expresie numai dacă aceştia indică spre obiecte
de acelaşi tip.
Ex.:
int *p, *q, k,j; p=&k; q=&j;
if (p<q) printf (“p indica o adresa de memorie mai mica decit q”);
printf(“p=%p q=%p\n”,p,q );
b) Comparare pointeri cu NULL
Operatorii de egalitate = = și ! = permit compararea pointerilor cu constanta NULL (definită în <stdio.h> )
Ex.:
#define NULL 0
void *p //p=pointer generic,nu este asociat nici unui tip de date
p==NULL;
p!=NULL //verifica daca lui p ii este asociata sau nu o valoare
În C++ se recomandă utilizarea comparației cu 0 a pointerilor nu cu NULL : Ex.: p= =0 si p!=0
2. Iniţializarea pointerilor se realizează utilizând următorul format: tip *nume =const;
unde tip = tipul de bază al pointerului, defineşte tipul variabilei la care indică acesta;
nume = numele variabilei pointer
const = expresie cu valoare constantă
Operatorul de atribuire ”=” permite inițializarea și atribuirea de valori unui pointer, precum în exemplul de
mai jos.
Ex.:
p=NULL; //initializare
*p=2; //atribuire
p=&nr; //atribuire
[Link]/scăderea unui nr. întreg la/dintr-un pointer
Se considera un pointer *p declarat astfel: tip *p;
Adunarea/scăderea unui număr întreg la/din acest pointer , p+n și p-n reprezintă adunarea/scăderea la
adresa indicată de p a valorii n*sizeof(tip).
Ex.: p=p+10; // p va indica la al 10-lea element de acelasi tip cu p
[Link]ăderea a doi pointeri
Se considera doi pointeri declarați astfel: tip *p1,*p2; Scăderea acestor doi pointeri, p1-p2 este permisă
numai pentru elemente de același tip, rezultatul reprezentând nr. de obiecte dintre cei doi pointeri..
Ex.:
int q; float j[3], *p1=&j[1],*p2=&j[3];
q=p2-p1; //variabilei q i se atribuie [Link] obiecte dintre cele doua adrese:2
[Link]/decrementarea pointerilor
Incrementarea/decrementarea nu reprezintă adunarea/ scăderea propriuzisă cu 1 (nici a adresei nici a
valorii spre care indică pointerul respectiv). Incrementarea/decrementarea semnifică adunarea/ scăderea
cu sizeof (tip), unde tip este tipul pointerului respectiv. După incrementarea/decrementarea unui pointer
-3-
acesta va indica spre elementul următor/anterior de același tip cu tipul său de bază.
În exemplele prezentate mai jos este ilustrată incrementarea și decrementarea unui pointer .
Ex.1: Dacă p1 are valoarea 2000, atunci p1++ are valoarea 2004 (nu 2001, pentru că int se reprezintă pe
4 octeți) și deci va indica spre următorul întreg .
int *p1; p1++;
Ex.2 : Daca p1 are valoarea 2000, p1-- are valoarea 1996
int *p1; p1--;
PROBLEME REZOLVATE
Ex.1: Programul este un exemplu de declarare a 2 pointeri la date de tip int si respectiv real
(float). Programul citeste de la tastatura o valoare intreaga x si o valoare de tip float
corespunzatoare lui y si apoi afiseaza adresele variabilelor x si y si valorile lor si ale patratelor
lor prin pointeri.
Varianta in C Varianta in C++
#include <stdio.h> #include <iostream>
#include <stdlib.h> using namespace std;
int main() int main()
{int x, *p1;float y,*p2; {int x, *p1;float y,*p2;
p1=&x; p2=&y; p1=&x; p2=&y;
printf("Introduceti o valoare intreaga x="); cout<<"Introduceti o valoare intreaga x=";
scanf("%d", &x); cin>>x ;
printf("Introduceti o valoare reala y="); scanf("%f", &y); cout <<"\nIntroduceti o valoare reala y=";
printf("\nAdresa lui x este:\n"); cin>>y;
printf("p1=%p\n", p1);printf("\nValoarea lui x cout<<"\nAdresa lui x este:"<<p1;
este:\n");printf("x=*p=%d\n",*p1); cout<<"\nValoarea lui x este:"<<*p1;
printf("\nValoarea lui x^2 este:\n"); cout<<"\nValoarea lui x^2 este:"<<*p1**p1;
printf("*p1^2=%d\n", *p1* *p1); cout<<"\nAdresa lui y este:"<<p2;
printf("\nAdresa lui y este:\n"); cout<<"\nValoarea lui y este:"<<*p2;
printf("p1=%p\n", p2); cout<<"\nValoarea lui y^2 este:"<<*p2* *p2;
printf("\nValoarea lui y este:\n"); return 0;}
printf("x=*p2=%.2f\n",*p2);
printf("\nValoarea lui y^2 este:\n");
printf("*p1^2=%.2f\n", *p2* *p2);
return 0;}
Rezultate: Aplicatie:
Să se modifice programul de mai sus astfel încât,
utilizând pointeri, să se afişeze rezultatul calculului
expresiei: x2+ 3y2 .
4
Ex.2 Programul este un exemplu de utilizare a pointerilor la date de tip caracter.
Varianta in C Varianta in C++
#include <stdio.h> #include <iostream>
int main() using namespace std;
{char c = 'A'; char *p = &c; int main()
printf("Initial variabila c este %c\n",c); {char c = 'A'; char *p = &c;
printf("Continutul variabilei c se poate afisa cout<<"Initial variabila c este "<<c<<endl;
utilizand\n"); cout<<"Continutul variabilei c se poate afisa
printf("a)variabila c sau b) pointerul *p=&c\n"); utilizand" <<endl;
printf("astfel a) c=%c b)*p=%c\n", c, *p); cout<<"a)variabila c sau b) pointerul
printf("\nSchimbarea valorii initiale se poate *p=&c"<<endl;
realiza:\n"); cout<<"astfel a)c="<<c<< "b)*p="<<*p<<endl;
printf("a) prin variabila sau b)prin pointer\n"); cout<<"\nSchimbarea valorii initiale se poate
printf("Introduceti un caracter:"); scanf("%c", p); realiza:"<<endl;
printf("astfel c=%c *p=%c\n", c, *p); cout<<"a) prin variabila sau b)prin pointer"<<endl;
return 0;} cout<<"Introduceti un caracter:";cin>>*p;
cout<<"astfel c="<<c<<" *p="<<*p;return 0;}
Rezultate: Aplicatie:
Sa se tiparească şi adresa variabilei c utilizand
pointerul *p.
Ex.3. Programul calculeaza si afiseaza rezultatele unor expresii cu numere intregi prin
intermediul pointerilor. Initial se considera i1=8 si se cere sa se afiseze i2=i1/2+1 direct si prin
intermediul pointerului *p1, apoi se va vor afisa rezultatele operatiilor aritmetice i1+i2, i1-i2, i1*i2,
i1/i2 prin pointeri.
Varianta in C Varianta in C++
#include <stdio.h> #include <iostream>
int main() using namespace std;
{int i1=8, i2, *p1, *p2; int main()
p1 = &i1; p2 = &i2; {int i1=8, i2, *p1, *p2;
printf("daca i1=8 si p1=&i1\n"); p1 = &i1; p2 = &i2;
printf("atunci operatiile sunt echivalente:\n"); cout<<"daca i1=8 si p1=&i1"<<endl;
printf("i2=i1/2+1=%d <=>i2=*p1/2+1=%d\n", cout<<"atunci operatiile sunt echivalente:"<<endl;
i1/2+1,*p1/2+1);i2=*p1/2+1; cout<<"i2=i1/2+1="<<i1/2+1<<" <=>
printf("i1=%d, i2=%d\n", *p1, *p2); i2=*p1/2+1="<<*p1/2+1<<endl;i2=*p1/2+1;
printf("operatiile aritmetice se pot realiza in 2 cout<<"i1="<<*p1<<", i2="<<*p2<<endl;
moduri:\n"); cout<<"operatiile aritmetice se pot realiza in 2
printf("a)i1+i2=%d,i1-i2=%d,i1*i2=%d, i1/i2=%d\n", moduri:"<<endl;
i1+i2,i1-i2,i1*i2,i1/i2); cout<<"a)i1+i2="<<*p1+*p2<<", i1-i2="<<i1+i2<<",
printf("b)*p1+*p2=%d,*p1-*p2=%d, *p1**p2=%d, i1*i2="<<i1*i2<<", i1/i2="<<i1/i2<<endl;
*p1/*p2=%d\n", *p1+*p2, *p1-*p2, cout<<"b)*p1+*p2="<<*p1+*p2<<", *p1-*p2="<<
*p1**p2,*p1/(*p2)); *p1-*p2<<", *p1**p2="<<*p1**p2<<",
return 0;} *p1/*p2="<<*p1/(*p2)<<endl;return 0;}
-5-
Rezultate: Aplicatie:
Să se modifice programul astfel încât sa
se afişeze şi adresele variabilelor i1 şi i2
Ex.4. In program se considera 4 variabile: de tip int, float, double si char carora le corespunde
cate un pointer:*a,*c,*d, *e. Programul realizeaza diverse operatii cu pointeri.
Varianta in C Varianta in C++
#include <stdio.h> #include <iostream>
#include <stdlib.h> using namespace std;
int main() int main()
{int i=1, *a,*a1; {int i=1, *a,*a1;
float x=1.,*c,*c1;
float x=1.,*c,*c1;
double pi=3.14, *d,*d1;
double pi=3.14, *d,*d1; char ch='A',*e,*e1;a=&i;
char ch='A',*e,*e1;a=&i; cout<<"i=variabila de tip int,i="<<i<<endl;
printf("i=variabila de tip int,i=%d\n",i); cout<<"a=variabila de tip pointer la int,a=&i="<<a<<endl;
printf("a=variabila de tip pointer la int,a=&i=%p\n",a); cout<<"a-1="<<a-1<<", a+1="<<a+1<<endl;
printf("a-1=%p a+1=%p\n", a-1,a+1); cout<<"sizeof(int):"<<sizeof(int)<<endl;
printf("sizeof(int):%d\n",sizeof(int) ); cout<<"comparare a si a+1: ";
printf("comparare a si a+1: "); if (a<(a+1)) cout<<a<<"<"<<a+1<<endl;
if (a<(a+1)) printf("%p < %p\n",a,a+1); else cout<<a<<">"<<a+1<<endl;a1=a+3;
else printf("%p > %p\n",a,a+1); cout<<"a1=a+3="<<a1<<endl;
cout<<"a1-a="<<a1-a<<endl;
a1=a+3;
cout<<"---------------------------------------------------"<<endl;
printf("a1=a+3=%p\n", a1); c=&x;
printf("a1-a=%d\n", a1-a); cout<<"x=variabila de float,x="<<x<<endl;
printf("---------------------------------------------------\n"); cout<<"c=variabila de tip pointer la float,
c=&x; c=&x="<<c<<endl;
printf("x=variabila de float,x=%f\n",x); cout<<"c-1="<<c-1<<" c+1="<<c+1<<endl;
printf("c=variabila de tip pointer la float, cout<<"sizeof(float):"<<sizeof(float)<<endl;c1=c+2;
c=&x=%p\n",c); cout<<"c+2="<<c1<<endl;
printf("c-1=%p c+1=%p\n", c-1,c+1); cout<<"c1=c+2;c1-c="<<c1-c<<endl;
printf("sizeof(float):%d\n",sizeof(float) ); cout<<"---------------------------------------------------"<<endl;
d=π
c1=c+2;
cout<<"pi=variabila de tip double,pi="<<pi<<endl;
printf("c+2=%p\n", c1); cout<<"d=variabila de tip pointer la
printf("c1=c+2;c1-c=%d\n", c1-c); double,d=&pi="<<d<<endl;
printf("---------------------------------------------------\n"); cout<<"d-1="<<d-1<<" d+1="<<d+1<<endl;
d=π cout<<"sizeof(double):"<<sizeof(double)<<endl;d1=d-2;
printf("pi=variabila de tip double,pi=%lf\n",pi); cout<<"d-2="<<d1<<endl;
printf("d=variabila de tip pointer la cout<<"d1=d-2;d1-d="<<d1-d<<endl;
double,d=&pi=%p\n",d); cout<<"---------------------------------------------------"<<endl;
printf("d-1=%p d+1=%p\n", d-1,d+1); e=&ch;
printf("sizeof(double):%d\n",sizeof(double) ); cout<<"ch=variabila de tip char,ch="<<ch<<endl;
cout<<"e=variabila de tip pointer la char,
d1=d-2;
e=&ch="<<(void *)e<<endl;
printf("d-2=%p\n", d1); cout<<"e-1="<<(void *)(e-1)<<" e+1="<<(void
printf("d1=d-2;d1-d=%d\n", d1-d); *)(e+1)<<endl;
printf("---------------------------------------------------\n"); cout<<"sizeof(char):"<<sizeof(char)<<endl;
e=&ch; e1=e+3;
6
printf("ch=variabila de tip char,ch=%c\n",ch); cout<<"e+3="<<(void *)e1<<endl;
printf("e=variabila de tip pointer la char, cout<<"e1=e+3,e1-e="<<e1-e<<endl;
e=&ch=%p\n",e); return 0;}
printf("e-1=%p e+1=%p\n", e-1,e+1);
printf("sizeof(char):%d\n",sizeof(char) );
e1=e+3;
printf("e+3=%p\n", e1);
printf("e1=e+3,e1-e=%d\n", e1-e);
return 0;}
Rezultate: Aplicație:
Să se modifice programul de mai sus
astfel încât, utilizând pointeri, să se
afişeze adresele: a+2, c1, d+2 si e+2.
PROBLEME PROPUSE
1. Sa se scrie un program care afiseaza solutia ecuatiei de gradul I unde coeficientii se citesc de
la tastatura utilizand pointeri si operatii prin pointeri
2. Sa se scrie un program care calculeaza si afiseaza valoarea functiei f(x) = x2-1 utilizand
pointeri si operatii prin pointeri.
-7-