Curs C++ | Sectiunea 16 – Pointeri Aritmetici

 

❓ Incepem aceasta sectiune cu o intrebare. Ce au in comun pointerii si sirurile?

💡 Daca vedeti un sir scris fara indice, acesta este mereu sinonim cu un pointer ce ar indica la primul element al sirului. Sa aruncam o privire pe un exemplu, pentru a intelege mai bine.

int *ptr, *ptr2, arr[3] = {1,2,3};
ptr = &arr[0];//adresa primului element al sirului
ptr2 = arr;//sirul

std::cout << *ptr << std::endl; //1
std::cout << *ptr2; //1

Dupa ce veti rula veti observa ca ambii pointeri, ptr si ptr2 indica la aceeasi zona de memorie, primul element al sirului.

PlantUML Syntax:</p>
<p>state ptr #Application</p>
<p>state ptr2 #Application</p>
<p>state arr{</p>
<p>state arr0 #Technology : 1</p>
<p>state arr1 #Technology : 2</p>
<p>state arr2 #Technology : 3</p>
<p>}</p>
<p>arr0 -[hidden]r> arr1</p>
<p>arr1 -[hidden]r> arr2</p>
<p>ptr –> arr0</p>
<p>ptr2 –> arr0</p>
<p>

 

Artimetica pointer-ilor

Aritmetica pointer-ilor este semnificativ diferita de cea a numerelor intregi, folosita pana acum.Ne permite urmatoarele operatii:

  • adunarea unei valori intregi la un pointer, avand ca rezultat tot un pointer (ptr + int -> ptr)
  • scaderea unei valori intregi dintr-un pointer, avand ca rezultat tot un pointer (ptr – int -> ptr)
  • scaderea unui pointer dintr-un pointer, avand ca rezultat un intreg (ptr – ptr -> int)
  • compararea a doi pointeri pentru egalitate sau inegalitate, avand ca rezultat un intreg de tip true sau false (ptr == ptr -> int; ptr != ptr -> int)

❗ Orice alta operatie inafara de cele mentionate mai sus este interzisa ori inutila pentru a fi executata cu pointeri.

 

Adunarea

Sa vedem cum functioneaza adunarea. Avand exemplul anterior, sa incercam sa adunam 1 la ptr2.

ptr2 = ptr2 + 1;
//se poate scrie si
ptr2++;
  • se ia in calcul la ce tip indica pointer-ul, in cazul nostru fiind int
  • se determina cati octeti (bytes) ocupa in memorie tipul respectiv (operatorul sizeof ese folosit automat)
  • valoarea ce ne dorim sa o adaugam se inmulteste cu dimensiunea rezultata de la operator
  • adresa ce este stocata la pointer-ul nostru este incrementata cu rezultatul inmultirii

Ca rezultatul, pointer-ul nostru se muta la urmatoarea valoare din memorie. Efectul acestui rezultat este prezentat mai jos:

PlantUML Syntax:</p>
<p>state ptr #Application</p>
<p>state ptr2 #Application</p>
<p>state arr{</p>
<p>state arr0 #Technology : 1</p>
<p>state arr1 #Technology : 2</p>
<p>state arr2 #Technology : 3</p>
<p>}</p>
<p>arr0 -[hidden]r> arr1</p>
<p>arr1 -[hidden]r> arr2</p>
<p>ptr –> arr0</p>
<p>ptr2 –> arr1</p>
<p>note right: ptr2 = ptr2 + 1</p>
<p>

❓ Ce s-ar intampla daca am aduna 2 la ptr2? In acest caz ptr2 ar fi incrementat cu 2 * sizeof(int), deci ptr2 ar fi mutat cu 2 valori de tip int  Astfel, el va indica la al treilea element din sirul arr, adica arr[2].

 

Scaderea

Bineinteles, scaderea este asemanatoare, doar ca ne mutam cu adresa in stanga pointer-ului initial si nu in dreapta.

❗ Poate va intrebati ce s-ar intampla daca am incerca, in exemplul nostru sa adunam 3 sau sa scadem 1, adica sa iesim in afara valorilor sirului nostru si a zonei de memorie. Nu vom primi nicio eroare, totul se va complila corespunzator dar valorile la care vom indica vor fi unele aletoare. La fiecare rulare veti observa alte valori.

💡 Trebuie sa va imaginati ca in general exista valori scrise in orice zona de memorie iar in momentul in care cream o variabila si ii atribuim o valoare, valoarea scrisa anterior in acea zona este inlocuita cu cea dorita.

PlantUML Syntax:</p>
<p>state ptr #Application</p>
<p>state ptr2 #Application</p>
<p>state ptr3 #Application</p>
<p>state arr{</p>
<p>state arr0 #Technology : 1</p>
<p>state arr1 #Technology : 2</p>
<p>state arr2 #Technology : 3</p>
<p>}</p>
<p>state random1 #IndianRed: 959545856</p>
<p>state random2 #IndianRed: 905724128</p>
<p>random1 -[hidden]r> arr</p>
<p>note left: ptr2 = ptr -1</p>
<p>arr0 -[hidden]r> arr1</p>
<p>arr1 -[hidden]r> arr2</p>
<p>ptr –> arr0</p>
<p>ptr2 –> random1</p>
<p>ptr3 –> random2</p>
<p>arr-[hidden]r> random2</p>
<p>note right: ptr3 = ptr + 3</p>
<p>

 

Scaderea intre pointeri

Am mentionat anterior ca scaderea dintre doi pointeri are ca rezulat un int. Sa vedem cum este calculat:

  • compilatorul va verifica mai intai daca ambii pointeri sunt de acelasi tip, in cazul nostru int
  • adresele stocate in pointeri sunt scazute
  • rezulatul scaderii este impartit la dimensiunea tipului de date

💡 Rezultatul final ne spune cate variabile de acel tip (in cazul nostru, int) se afla intre cele doua adrese stocate in pointeri. Spre exemplu:

int count;
ptr = arr;
ptr2 = ptr + 2;

count = ptr2 - ptr;
std::cout << count; //2

Obtinem o valoarea mai mare ca 0 daca ptr2 indica la o zona de memorie aflata dupa ptr, altfel vom avea un rezultat mai mic decat 0.

 

Aici se termina si aceasta sectiune. Daca aveti intrebari suplimentare, puteti folosi informatiile de aici 🙂 .Toate diagramele au fost create folosind PlantUML.

➡ Sectiunea anterioara:Curs C++ | Sectiunea 15 – Pointeri

➡ Sectiunea urmatoare:Curs C++ | Sectiunea 17 – Functii

You may also like...