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




Pointeri

Informatica


Pointeri



Orice variabila are: continut

adresa (de multe ori e nevoie de lucrul cu adresele variabilelor)

Def:

Pointerii sunt variabile sau constante care au ca valori adrese ale unor variabile, adica adrese ale unor locatii de memorie.

Pointerii  permit calcule cu adrese

folositi pt. scrierea unor programe mai eficiente d.p.d.v. al timpului de executie

memoriei utilizate

Tipuri de pointeri:

D.p.d.v. al continutului zonei de memorie adresate:

- pointeri de date (obiecte) - contin adresa unei variabile din memorie;

- pointeri generici (numiti si pointeri void) - contin adresa unui obiect oarecare, de tip neprecizat;

- pointeri de functii - contin adresa codului executabil al unei functii.

Utilizare in C pentru a crea structuri dinamice de date construite din blocuri de memorie

pentru a opera cu parametrii transferati functiilor la apelul acestora

pentru a accesa informatia stocata in tablouri.

Declararea si initializarea variabilelor pointer

Pentru pointerii de date:

tip nume_pointer;

in care tip (care se mai numeste si tip de baza sau tip utilizator) reprezinta tipul valorii care se gaseste la adresa pastrata in nume_pointer, deci indica tipul de variabile catre care poate sa pointeze pointerul respectiv.

Exemple:

int a, b, *p, *q; // p, q pointeaza catre variabile de tip int

float c, d, *p1, *q1; // p1, q1 pointeaza catre variabile de tip float

Obs:

Caracterul "*" poate fi plasat in mai multe feluri, a. i. de declaratiile urmatoare sunt echivalente:

int *p;

int * p;

int* p;

Pentru pointerii generici:

void nume_pointer;

Un pointer generic nu are asociat un tip de date precis. De aceea, in cazul unui pointer vid, dimensiunea zonei de memorie adresate si interpretarea informtiei nu sunt definite.

Initializarea pointerilor consta in precizarea adresei unui obiect definit in memorie. Daca p este numele unui pointer, atunci *p reprezinta valoarea de la adresa la care 'pointeaza' pointerul p.

Variabilele de tip pointer pot fi initializate la declarare. De asemenea, li se pot atribui adrese pe parcurs.

Exista doi operatori unari care permit utilizarea variabilelor pointer:

q       & - operatorul adresa (de referentiere) - pentru aflarea adresei din memorie a unei variabile;

Ex

Se atribuie pointerului p adresa variabilei x ( p pointeaza catre x)

 
int x;

p = &x;

q       - operatorul de indirectare (de dereferentiere) - care furnizeaza valoarea din zona de memorie spre care pointeaza pointerul operand.

Ex

*p reprezinta valoarea variabilei x.

Obs: Operatorii * si & sunt complementari.

Exemplu:

int a=5, b=10, v[10];

int *p; // p pointeaza catre variabile de tip intreg

p = &a; // p pointeaza la a

b = *p; // b are valoarea de la adresa lui a , adica 5

*p = 0; // a are acum valoarea 0

p = &v[0];  // p pointeaza acum la v[0], deci are ca valoare adresa elementului v[0]

*p = 10*b; // v[0] are acum valoarea 10*5 = 50

Obs: p este de tipul int * (p este de tip pointer spre int)

1. declaratia int *p poate fi interpretata: *p este de tipul int (continutul adresei spre care

pointeaza variabila p este de tipul int)

2. atribuirea a = 10 este echivalenta cu p = &a; *p = 10;

Erori in cazul utilizarii pointerilor

1. absenta initializarii - eroarea cea mai frecventa in cazul utilizarii pointerilor

Astfel, in urma unei declaratii si initializari de forma:

int *p;

*p = 2;

pointerul  p este neinitializat => valoarea 2 va fi scrisa la o adresa de memorie necunoscuta => coruperea memoriei, rezultare eronate sau imprevizibile, terminarea

fortata a programului

Deci, inainte de dereferentierea pointerilor acestia trebuie sa fie initializati cu adrese valide.

2. o referinta nevalida care poate fi produsa printr-o atribuire de forma:

p1=p2;

unde p1 si p2 sunt pointeri, iar p2 este neinitializat.

Orice referinta la *p1 va produce o referinta nevalida.

referinta la pointeri nuli. Astfel, daca p este un pointer la tipul intreg, secventa:

p = 0;

*p = 10;

este nevalida deoarece nu exista nici un bloc de date la care sa pointeze p.

Astfel, incercarea de a citi sau scrie acel bloc de date conduce la o referinta nevalida.

Operatii cu pointeri

1) Compararea pointerilor

Comparatiile logice = =, !=, <, >, <=, >= sunt valabile si in cazul pointerilor.

Exemplu:

int p1, p2;

if (p1<p2) cout<<"p1="<<p1<<"<"<<"p2="<<p2<<'n';

else cout<<"p1="<<p1<<">="<<"p2="<<p2<<'n';

De asemenea, se poate realiza compararea unui pointer cu valoarea nula, pentru a verifica daca acesta adreseaza un obiect. Compararea se face cu constanta simbolica NULL (definita in header-ul stdio.h) sau cu valoarea 0.

Exemplu:

if (!p1)

. . . . . ; // pointer nul

else . . . . ; // pointer nenul

2) Adunarea si scaderea unui intreg dintr-un pointer

Rezultatul operatiei p+n, respectiv p-n, unde p este un pointer si n este un intreg este: p+n*r, respectiv p-n*r, unde r reprezinta numarul de octeti folositi pentru pastrarea in memorie a datelor de tipul celor spre care pointeaza p.

Un caz particular al adunarii sau scaderii dintre un pointer de date si un intreg (n=1) il reprezinta incrementarea si decrementarea unui pointer de date:

Fie declaratia:

int *p;

Instructiunile:

++p; si p++;   respectiv: --p; si p--;

maresc, respectiv micsoreaza valoarea lui p cu o unitate.

3) Scaderea pointerilor

In limbajul C nu este permisa adunarea pointerilor, dar este permisa scaderea a doi pointeri de obiecte de acelasi tip, rezultatul fiind o valoare intreaga care reprezinta numarul locatiilor de memorie aflate intre adresele la care pointeaza cei doi pointeri care se scad.

Exemplu:

Fie p un pointer spre elementul v[i] al tabloului v si q un pointer spre elementul v[i+n] al aceluiasi tablou. Atunci diferenta q-p are valoarea n.

Pointeri si tablouri

Numele unui tablou este un pointer constant (valoarea lui nu poate fi schimbata) care are ca valoare adresa primului element din tablou.

Diferenta dintre numele unui tablou si o variabila pointer este aceea ca unei variabile de tip pointer i se pot atribui valori la executie, lucru imposibil pentru numele unui tablou. Acesta tot timpul are ca valoare adresa primului sau element.

Tinand cont de acest lucru si de operatiile aritmetice aplicabile variabilelor pointer, orice operatie care se face folosind indicii tablourilor poate fi facuta, chiar mai rapid, prin folosirea pointerilor.

Obs: legatura dintre pointeri si tablouri unidimensionale poate fi evidentiata astfel:

Fie v un tablou (vector) cu 10 elemente intregi (fie declaratia: int v[10])

v[0] v[1] ........ v[9]

v=&v[0] v+1=&v[1] . . . v+9=&v[9]

v=v[0] (v+1)=v[1] . . . (v+9)=v[9]

In concluzie, deoarece numele tabloului este un pointer constant, avem echivalentele:

v+i & v[i]

v[i] (v+i)

Deci variabilele indexate pot fi transformate in expresii cu pointeri si avem echivalentele:

Adresa

Valoare

Notatie indexata

Notatie cu pointeri

Notatie indexata

Notatie cu pointeri

&v

v

v[0]

*v

&v[1]

v+1

v[1]

*(v+1)

&v[i]

v+i

v[i]

*(v+i)

&v[n-1]

v+n-1

v[n-1]

*(v+n-1)

Intr-adevar: v[i]=*(v+i)=*(i+v)=i[v]

 
Obs: in C, daca v este un tablou de intregi avem urmatoarea echivalenta:

v[i] º i[v]

Exemplu: initializarea elementelor unui tablou:

int x[10], *pi;

for(pi=x;pi<&x[10];pi++)

*pi=0;

 

int x[10], i;

for(i=0;i<10;i++)

x[i]=0;

 
fara pointeri: cu pointeri:

Exemplu: adunarea elementelor unui tablou cu 10 componente intregi folosind pointeri:

#include <iostream.h>

void main()

Exemplu: Sa se citeasca elementele unui vector cu maxim 10 elemente intregi si sa se inlocuiasca elementul minim din vector cu o valoare introdusa de la tastatura, folosind lucrul cu pointeri.

#include <iostream.h>

void main()

aflarea elementului minim din vector si a pozitiei acestuia

Am utilizat:

v=v[0]

(v+i)=v[i]

 
min=v; indice=0;

for (i=0; i<n; i++)

if (min>=(v+i))

citirea valorii cu care se va inlocui elementul minim si inlocuirea acestuia

 
cout<<"valoarea de inlocuire:"; cin >> val;

(v+indice)=val;

afisarea noului vector

 
for (i=0; i<n; i++)

cout<<(v+i)<<" ";

Obs: legatura dintre pointeri si tablouri multidimensionale poate fi evidentiata astfel:

Fie A un tablou bidimensional(matrice) cu 4 linii si 5 coloane (fie declaratia: int A[4][5])

Matricea A are 4 linii si 5 coloane.

Numele tabloului bidimensional, A, refera intregul tablou;

A[0] refera prima linie din tablou;

A[0][0] refera primul element al tabloului.

 
A[

A[

A[

A[

In concluzie, deoarece numele tabloului este un pointer constant, avem echivalentele:

A = (A + 0) A[0]

A=(A)(A[0])=(A[0]+0) A[0][0]

*(*(A+i)+j) *(A[i]+j) A[i][j]

Exemplu: Sa se citeasca elementele unei matrici cu maxim 10 randuri si 10 coloane cu elemente intregi si sa se afiseze, folosind lucrul cu pointeri.

#include <iostream.h>

void main()

afisarea elementelor matricii utilizand

*(*(a+i)+j)=a[i][j]

 
for (i=0; i<n; i++)

Tablouri de pointeri

Deoarece pointerii sunt variabile si ei pot fi stocati in tablouri. Un tablou de pointeri se declara la fel ca orice tablou, diferenta constand in faptul ca elementele tabloului sunt pointeri.

Obs: tablourile de pointeri se utilizeaza frecvent pentru a prelucra succesiuni de siruri de caractere. Intr-un program se intalnesc adesea siruri de caractere care trebuie tratate in mod unitar. Atunci se poate defini un tablou de pointeri, fiecare element al tabloului fiind un pointer spre un astfel de sir de caractere. 

Efectul unei astfel de declaratii este alocarea de memorie

pentru un tablou cu "dim" componente

care pastreaza adrese ale unor valori de tipul "tip".

 
Modul general de declarare a unui tablou de pointeri:

tip nume_tablou[dim];

Initializarea componentelor tabloului se va face prin atribuiri de adrese de variabile de acelasi tip cu tipul de baza declarat:

nume_tablou[indice]=&variabila;

Pointeri la pointeri

O secventa de forma:

tip **nume_variabila;

declara variabila "nume_variabila" ca pointer catre un pointer de tipul "tip".

Valoarea variabilei nume_variabila va putea fi o adresa la care se pastreaza adresa unei valori de tipul "tip".

Valoarea de tipul "tip" se va putea obtine prin apelul:

**nume_variabila.

Exemplu: Functia main( ) urmatoare acceseaza aceeasi zona de memorie in care este depozitata valoarea reala 10 in moduri diferite, cu ajutorul a trei variabile p, q, r.

#include <iostream.h>

void main()


Document Info


Accesari: 3356
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 )