curs7_an1_sem1_14_15
DESCRIPTION
Curs7_an1_sem1_14_15TRANSCRIPT
-
CURS 7
Pointeri 1
-
CUPRINS
1. Noiuni introductive
2. Operatori specifici pentru pointeri
3. Operaii cu pointeri
4. Apelul prin adres utiliznd pointeri
5. Pointeri i referine
6. Indirectarea multipl
7. Pointeri constani i pointeri ctre constante
8. Tablouri i pointeri
9. Funcii pentru lucrul cu iruri de caractere
10. Pointeri spre funcii
11. Transferarea de argumente ctre funcia main( )
12. Alocarea dinamic a memoriei
13. Funcii pentru manipularea zonelor de memorie 2
-
1. NOIUNI INTRODUCTIVE
Tipul pointer (indicator) reprezint adresa unei locaii de memorie
adresele sunt valori numerice ntregi fr semn
Tipuri de pointeri:
pointeri de date:
conin adresa unor variabile sau constante din memorie
pointeri de funcii: conin adresa codului executabil din funcii
pointeri de obiecte:
conin adresa unui obiect
pointeri generici sau pointeri void:
conin adresa unui obiect oarecare 3
-
NOIUNI INTRODUCTIVE
Pointerii de date se declar astfel:
tip *nume_pointer;
Pointerii generici se declar astfel:
void *nume_pointer;
Exemplu:
int *nptr;
float *a, rezultat;
int *tabptr[10];
void *pgen;
4
-
2. OPERATORI SPECIFICI PENTRU POINTERI
Operatorul & (adresare sau refereniere):
permite aflarea adresei unei variabile oarecare:
&nume_var
rezultatul este un pointer la tipul variabilei
Operatorul * (indirectare sau derefereniere):
se folosete pentru a afla ce se gsete la o adres:
*nume_pointer ... la adresa nume_pointer ...
5
-
OPERATORI SPECIFICI PENTRU POINTERI
expresia *nume_pointer poate fi folosit att pentru a obine valoarea obiectului ct i pentru a o modifica:
var = *nume_pointer ;
*nume_pointer = expr;
Orice variabil pointer trebuie definit cu o valoare valid (0 sau NULL, nu e valid, deci cu adresa unei date) nainte de a fi utilizat:
int *p;
...
*p = 10; // eroare, pentru ca lui p nu i s-a asignat o valoare
6
-
OPERATORI SPECIFICI PENTRU POINTERI
Exemplu:
void main(void)
{
int i=10, *ptri;
ptri = &i;
printf("Valoare var : %d \nLa adresa var : %d" , i, *ptri);
*ptri = 20;
printf("Valoare var : %d \nLa adresa var : %d" , i, *ptri);
}
7
-
OPERATORI SPECIFICI PENTRU POINTERI
In C/C++ se permite ca orice tip de pointer s pointeze oriunde n memorie, tipul pointerului determinnd modul n care va fi tratat obiectul pointat:
Un pointer de un anumit tip nu va fi folosit s pointeze o dat de alt tip:
int q;
double *dp;
dp = &q;
*dp = 20.5;//voi scrie 8 octei
8
-
OPERATORI SPECIFICI PENTRU POINTERI
sau
int *p;
double q, temp;
temp=20.5;
p=&temp;
q=*p; //iau doar cat e specific unui int
printf (\nprin pointer int luat de la un double: %lf,q);
9
-
OPERATORI SPECIFICI PENTRU POINTERI
Pointerii generici (void *) nu sunt asociai unui anumit tip de date:
dimensiunea zonei de memorie adresate i interpretarea datelor din acea zon nu sunt definite
Aceti pointeri pot fi utilizai cu mai multe tipuri de date, ns numai cu operatorul de conversie explicit (cast):
10
-
OPERATORI SPECIFICI PENTRU POINTERI
int x;
float y;
void *p;
...
p=&x; // lui p i se atribuie adresa de memorie
unde pot fi intregi
*(int*)p = 10;
p=&y; // lui p i se atribuie adresa de memorie
unde pot fi flotanti
*(float *)p = 20.5;
11
-
OPERATORI SPECIFICI PENTRU POINTERI
Operatorul cast poate modifica semnificaia pointerilor:
int *pi;
float *pf;
...
*((char*)pf) -> primul octet al unei variabile de tip float
*((char*)pf+1) -> al doilea octet al unei variabile de tip float
Construcia (char*) este folosit pentru accesul pe octet la zone de memorie de mrimi diferite
12
-
3. OPERAII CU POINTERI
Cu ajutorul pointerilor se pot efectua operaii de:
atribuire
comparare
adunare
scdere
incrementare
decrementare
In operaii se ine cont de faptul c adresele care reprezint pointerii au valori numerice ntregi fr semn
13
-
OPERAII CU POINTERI Atribuirea
Dac:
tip1 *id_ptr1;
tip2 *id_ptr2;
id_ptr1 = id_ptr2;
Avem urmtoarele cazuri:
tip1 este void, atunci tip2 poate fi oarecare
tip2 este void, atunci tip1 poate fi oarecare (la
asignare se foloseste cast)
tip1 si tip2 sunt identice, atribuirea este corect
tip1 si tip2 difer, atunci compilatorul genereaz un avertisment sau o eroare 14
-
OPERAII CU POINTERI
#include
using namespace std;
#include
void main(){
void *pg;
int *pi;
double *pd;
int nota=10;
double media=9.97;
pi=¬a;
pg=pi;
cout
-
OPERAII CU POINTERI
pd=&media;
pg=pd;
cout
-
OPERAII CU POINTERI Compararea a doi pointeri
Se face cu operatorii relaionali, dar numai n cazul n care pointerii pointeaz pe obiecte de acelai tip
Exemplu:
int *p1, *p2, i, j;
...
p1=&i;
p2=&j;
if (p1 < p2)
printf ("p1= %n p2 = %n\n", p1, p2);
17
-
OPERAII CU POINTERI
Operatorii == i != pot fi folosii pentru a compara pointeri cu o constant special NULL definit de obicei n stdio.h prin:
#define NULL 0
Pentru un pointer generic (void *p) se pot face comparaiile:
p == NULL i p != NULL
In C++ este recomandabil a folosi:
if (p == 0) if (!p)
if (p != 0) if (p)
18
-
OPERAII CU POINTERI
Adunare, scdere i incrementare, decrementare
Pot fi adugate sau sczute doar cantiti ntregi
Operaiile se efectueaz relativ la tipul pointerului (int, float, char, etc.)
Fie declaraia: tip *id_ptr;
Operaiile: id_ptr + n, id_ptr - n
corespund adugrii/scderii la adresa obinut n cadrul variabilei id_ptr a valorii: n * sizeof(tip)
19
-
OPERAII CU POINTERI
Analog se efectueaz i operaiile de incrementare/decrementare doar c n este= 1/-1
Rezultatul este corect doar atunci cnd pointerul adreseaz un tablou i prin opearatia aritmetic se produce o deplasare n interiorul limitelor tabloului
20
-
OPERAII CU POINTERI Exemplu:
float *fp1, *fp2, tf[10]; // sizeof (float) = 4
double *dp, td[10[; // sizeof (double) = 8
...
fp1 = &tf[0]; //tf
dp = &td[9]; // adresa celui de-al 10-lea element
fp2 = fp1+5; // fp2 va contine : adresa lui tf + 5*4
dp = dp-2; // dp va contine : adresa lui dp - 2*8
fp1++; // fp1 va contine : adresa lui fp1 + 1*4
dp--; // dp va contine : adresa lui dp - 1*8
21
-
OPERAII CU POINTERI
Operaia de incrementare/decrementare se poate aplica:
asupra pointerului nsui
asupra obiectului pe care l pointeaz
Dac se folosete varianta:
int *p, q=17, v;
p=&q;
v=*p++; // nti se aplica * i apoi ++ asupra pointerului
Dac se folosete varianta:
v = (*p)++; // se obine nti coninutul de la adresa p
// care apoi se incrementeaz cu 1
22
-
OPERAII CU POINTERI
. (programul de la slide-ul 15)
res=(*pd)++;
cout
-
OPERAII CU POINTERI
#include
using namespace std;
#include
void main(){
int l=1, j=5,k, *p;
p=&l;
*p=2;//modific l, operatie asupra continut
cout
-
OPERAII CU POINTERI
p=&l;
cout
-
26
-
OPERAII CU POINTERI
Scderea a doi pointeri
Este permis numai pentru pointeri de acelai tip ce refer un tablou, rezultatul fiind o valoare care reprezint diferena de adrese divizat la dimensiunea tipului de baz
Adunarea pointerilor nu este permis !
Exemplu:
float l,ft[9];
float *p1=&ft[4], *p2=&ft[2];
...
l = p2-p1; // l = (adresa p2- adresa p1)/4
Datorit rolului tipului la adunare i scdere, operanzii nu pot fi pointeri void sau pointeri spre
funcii 27
-
4. APELUL PRIN ADRES UTILIZND POINTERI
Transferul parametrilor prin valoare (implicit):
const n ncrcarea valorii parametrilor efectivi n zona de memorie a parametrilor formali
dac parametrul efectiv este o variabil, orice operaie efectuat n funcie asupra parametrului formal nu afecteaz variabila
spunem c se lucreaz cu copii ale parametrilor efectivi
Dac vrem ca o funcie s modifice o variabil parametru efectiv, atunci trebuie s transmitem funciei, la apel, adresa variabilei:
ca i parametri formali se pot folosi pointeri unde se vor copia aceste adrese
28
-
APELUL PRIN ADRES UTILIZND POINTERI
void schimba1(int a, int b)
{
int temp;
temp=a;
a=b;
b=temp;
}
Apel:
schimba1(x, y);
29
void schimba2(int *a, int *b)
{
int temp;
temp=*a;
*a=*b;
*b=temp;
}
Apelul:
schimba2(&x, &y);
-
APELUL PRIN ADRES UTILIZND POINTERI
Dac la apelul unei funcii se folosete ca i argument un tablou, funcia va primi doar adresa acelui tablou, adic adresa primului element din tablou
Variante:
parametrul formal este declarat ca un tablou fr dimensiune
int cauta(int p[ ], int n, int x );
parametrul formal este declarat ca un pointer ctre tipul tabloului, argumentul folosit ca i parametru efectiv fiind adresa tabloului asupra cruia se fac operaii n funcie
int cauta(int *p, int n, int x ); 30
-
APELUL PRIN ADRES UTILIZND POINTERI
// cautare pe un tablou
int cauta(int *p, int n, int x );
int cauta(int *p, int n, int x)
{
int i;
for(i=0; i
-
5. POINTERI I REFERINE
Referinele, ca i pointerii, conin adrese de memorie
Se declar cu ajutorul operatorului de adresare ("&) i se iniializeaz obligatoriu la inceput cu o adres (a unei variabile sau a unei constante), fiind un alias al
ei:
int i;
int &r = i; //alias
32
-
POINTERI I REFERINE
Accesul la o variabil prin intermediul unei referine se face simplu fr a mai folosi operatorul de indirectare ca n cazul pointerilor:
int i; int i;
int *p; int &r = i;
...
p = &i;
*p = 100; // i = 100 r = 1000; // i = 1000
33
-
POINTERI I REFERINE
Diferene ntre pointeri i referine:
dup modul de declarare:
* pentru pointeri
& pentru referine
dup modul de utilizare:
pointerii:
se asociaz unei variabile cu operatorul &, pentru accesul la valoare se utilizeaz operatorul *
pot fi asociai mai multor variabile la momente diferite de timp i deci pot conine adrese diferite
referinele:
se asociaz unei variabile i numai uneia la definire
conin tot timpul adresa aceleiai variabile fiind de fapt o redenumire (alias) a variabilei
li se asociaz valori pe baza unei atribuiri simple 34
-
POINTERI I REFERINE
Restricii:
nu sunt permise referine la referine, pointeri la referine, referine la cmpuri de bii, tablouri de referine, dar putem avea referine la pointeri
o referin nu poate avea valoarea NULL
o referin nu poate fi asociat unei alte variabile
Utilizare:
se folosesc rar variabile referine simple
uzual se folosesc la transmiterea parametrilor prin
referin, caz n care indirectarea este ascuns i nu este necesar dereferenierea n funcie (utilizarea operatorului *) 35
-
POINTERI I REFERINE
// varianta cu pointeri
void schimba2(int *a, int *b)
{
int temp;
temp = *a;
*a = *b;
*b = temp;
}
apelul :
schimba2(&i, &j);
36
// varianta cu referine
void schimba3(int &a, int &b)
{
int temp;
temp = a;
a = b;
b = temp;
}
apelul :
schimba3(i, j);
-
POINTERI I REFERINE
Rezultatul unei funcii se poate transfera prin referin astfel:
int& func(...)
{
static int var;
...
return (&var);
}
Trebuie evitat returnarea adresei (prin pointer sau referin) unui obiect automatic, obiect care se distruge la ieirea din funcie
37
-
6. INDIRECTAREA MULTIPL
Cnd un pointer pointeaz alt pointer avem un proces de indirectare multipl:
Pointer ctre pointer -----> Pointer -----> Obiect
Primul pointer conine adresa celui de-al doilea pointer, pointer care pointeaz locaia care va conine obiectul,...
Declararea se face utiliznd un asterisc suplimentar n faa numelui pointerului:
char **pm, *p, ch;
...
p = &ch;
pm = &p;
**pm = 'A'; // lui ch i s-a asignat valoarea A
prin 2 pointeri 38
-
7. POINTERI CONSTANI I POINTERI CTRE CONSTANTE
Exist pointeri ctre constante i pointeri constani (care nu pot fi modificai):
pointeri ctre constante
const char *str1 = "pointer catre constanta";
//str1[0] = 'P'; // incorect
str1 = "ptr la const"; // ok
pointeri constani
char *const str2 = "pointer constant ";
//str2 = "ptr const"; // incorect
str2[0] = 'P'; // ok
39
-
POINTERI CONSTANI I POINTERI CTRE CONSTANTE
pointeri constani ctre constante
const char *const str3 = "pointer constant la constanta";
//str3 = "ptr const la const"; // incorect
//str3[0] = 'C'; // incorect
un pointer poate, indirect, modifica totui o variabil declarat cu modificatorul const astfel:
*(tip *)&var;
int const kk=7;//const int const kk=7;
int k_var= *(int*)&kk; // val lui kk se depune in k_var
cout
-
POINTERI CONSTANI I POINTERI CTRE CONSTANTE
O funcie care are ca parametri formali pointeri, dar nu are voie s modifice datele pointate de parametru efectiv arat astfel:
void cifru(const char *src, char *dest)
{
while(*src)
{
*dest = *src + 5;
dest++;
src++;
}
} 41
-
ALTE CONSIDERAII REFERITOARE LA POINTERI
In limbajul C/C++ se folosesc des funcii care returneaz pointeri
Exemplu:
char *strcpy(char *dest, const char *src);
Astfel de funcii se mai folosesc i pentru alocarea dinamic a memoriei, prelucrarea listelor, arborilor, ...
42
-
Exemplul 1:
#include void main(void) { int n, *pn; float r, *pr; printf("\nIntroduceti un numar intreg: "); scanf("%d", &n); pn = &n; printf("\nReprezentarea in memorie a lui %d este: 0x%02x%02x%02x%02x\n", n, *((unsigned char *)pn+3), *((unsigned char *)pn+2), *((unsigned char *)pn+1), *((unsigned char *)pn));
43
-
printf("\nIntroduceti un numar real: ");
scanf("%f", &r);
pr = &r;
printf("\nReprezentarea in memorie a lui %f este:
0x%02x%02x%02x%02x\n", r,
*((unsigned char *)pr+3),
*((unsigned char *)pr+2),
*((unsigned char *)pr+1),
*((unsigned char *)pr));
}
44
-
Exemplul 2:
#include void schimba1(int a, int b); void schimba2(int *a, int *b); void schimba3(int &a, int &b); void main(void) { int x, y; int *px, *py; int &rx=x, &ry=y; printf("\nIntroduceti valoarea lui x: "); scanf("%d", &x); printf("\nIntroduceti valoarea lui y: "); scanf("%d", &y); 45
-
schimba1(x, y);
printf("\nNoile valori sunt: x = %d, y = %d", x, y);
schimba2(&x, &y);
printf("\nNoile valori sunt: x = %d, y = %d", x, y);
schimba3(x, y);
printf("\nNoile valori sunt: x = %d, y = %d\n", x, y);
}
46
-
void schimba1(int a, int b){
int temp;
temp=a;
a=b;
b=temp;
}
void schimba2(int *a, int *b){
int temp;
temp = *a;
*a = *b;
*b = temp;
}
void schimba3(int &a, int &b){
int temp;
temp = a;
a = b;
b = temp;
}
47
-
Exemplul 3:
#include
#include
void main(void){
int n, *p;
int tab[ ] = {1, 3, 5, 7, 9};
n = sizeof(tab)/sizeof(int);
p = &tab[0];
printf("\nElementele tabloului cu ++ de la inceput sunt: ");
for(int i=0; i
-
p = &tab[0];
printf("\nElementele tabloului de la inceput sunt: ");
for(int i=0; i