Pointeri și Vectori în C++

Ghid vizual explicativ și aplicații practice interactive

1. Ce este un Pointer? Relația cu Memoria RAM

Memoria RAM poate fi văzută ca un șir lung de casete numerotate. Fiecare casetă are o adresă unică de memorie (exprimată hexazecimal: 0x7ffd1000) și poate stoca o valoare.

Un pointer este o variabilă care stochează drept valoare adresa de memorie a altei variabile.

Operatori:
• &x → Adresa variabilei x (Adresare)
• *p → Valoarea aflată la adresa stocată în pointerul p (Dereferențiere)

Vizualizare: Variabilă simplă vs. Pointer

0x7ffd1000
int x
42
0x7ffd1004
int *px
➔ 0x7ffd1000

Explicație: Variabila px stochează adresa 0x7ffd1000. Executând cout << *px;, calculatorul merge la adresa 0x7ffd1000 și citește valoarea 42.

2. Relația dintre Pointeri și Vectori (Tablouri)

În C++, numele unui vector reprezintă de fapt un pointer constant către primul său element. Adică v este echivalent cu &v[0].

Aritmetica pointerilor: Adăugarea unui număr i la un pointer (v + i) mută adresa cu i * sizeof(tip) bytes în memorie, ajungând la elementul v[i].

Echivalențe fundamentale:
• v + i este identic cu &v[i] (Adresa elementului i)
• *(v + i) este identic cu v[i] (Valoarea elementului i)

Vizualizarea memoriei pentru un vector int v[3] = {10, 20, 30};

0x1000 (v / &v[0])
v[0]
10
0x1004 (v + 1)
v[1]
20
0x1008 (v + 2)
v[2]
30

3. Aplicații Interactive

Analizează secvențele de cod C++ și determină ce se afișează în urma execuției.

Exercițiul 1: Dereferențierea simplă Basic

Ce va afișa codul C++ de mai jos?

int a = 15;
int *p;
p = &a;
cout << *p;
Starea Memoriei RAM:
0x2000
int a
15
0x2004
int *p
➔ 0x2000

Explicație: Pointerul p primește adresa variabilei a (0x2000). Prin dereferențierea *p, se accesează valoarea stocată la această adresă, adică 15.

Exercițiul 2: Pointer Dublu (Pointer la Pointer) Mediu

Ce se va afișa în urma execuției?

float val = 8.5;
float *pf, **ppf;
pf = &val;
ppf = &pf;
val += 3.5;
cout << **ppf;
Starea Memoriei RAM:
0x3000
float val
12 (inițial 8.5)
0x3004
float *pf
➔ 0x3000
0x3008
float **ppf
➔ 0x3004

Explicație:ppf arată către pf, iar pf arată către val. Instrucțiunea val += 3.5 modifică valoarea la 12. Dereferențierea dublă **ppf accesează direct val, afișând 12.

Exercițiul 3: Accesarea elementelor din vector prin offset Vectori & Pointeri

Știind că tabloul b conține elementele: 7, 3, 9, 14, 5, 2, ce se va afișa?

int b[6] = {7, 3, 9, 14, 5, 2};
cout << *(b + 3);
Starea Memoriei RAM:
0x4000 (b+0)
b[0]
7
0x4004 (b+1)
b[1]
3
0x4008 (b+2)
b[2]
9
0x400C (b+3)
b[3]
14

Explicație: Expresia *(b + 3) este echivalentă cu b[3]. Indexarea începe de la 0 (b[0]=7, b[1]=3, b[2]=9, b[3]=14). Rezultatul afișat este 14.

Exercițiul 4: Parcurgerea unui vector cu un pointer Buclă cu Pointeri

Ce se va afișa în urma execuției următoarei bucle?

float a[5] = {2.0, 4.5, 6.1, 8.3, 10.0};
float *pa;
for(pa = a; pa < a + 3; pa++) {
    cout << *pa << " ";
}
Mecanismul de parcurgere:

• La prima iterare: pa = a + 0 (adresa &a[0]) ➔ Afișează 2.0

• La a doua iterare: pa++ avansează la &a[1] ➔ Afișează 4.5

• La a treia iterare: pa++ avansează la &a[2] ➔ Afișează 6.1

• Condiția pa < a + 3 oprește bucla înainte de a[3].

Exercițiul 5: Modificarea indirecta a valorilor Operatori de atribuire

Care vor fi valorile afișate pentru variabilele x și y?

int x = 4, y = 10;
int *px = &x;
int *py = &y;
*px += 5;
*py -= 4;
cout << x << " " << y;
Evoluția stării memoriei:

1. *px += 5 modifică valoarea din x: 4 + 5 = 9.

2. *py -= 4 modifică valoarea din y: 10 - 4 = 6.

Afișajul final este 9 6.

Exercițiul 6: Modificarea elementelor unui vector prin pointeri Modificare Tablou

Cum va arăta tabloul tab (inițial 10, 20, 30, 40) după execuția codului?

int tab[4] = {10, 20, 30, 40};
for(int i = 0; i < 3; i++) {
    *(tab + i) = i * 2;
}
Modificările element cu element:

• i = 0: *(tab + 0) = 0 ➔ tab[0] devine 0

• i = 1: *(tab + 1) = 2 ➔ tab[1] devine 2

• i = 2: *(tab + 2) = 4 ➔ tab[2] devine 4

• Elementul tab[3] nu a fost modificat de buclă și rămâne 40.

Vectorul final este: 0 2 4 40.

Exercițiul 7: Declararea implicită a tablourilor și utilizarea offset-ului Aritmetică de pointeri

Ce se va afișa în urma execuției secvenței următoare?

int a[] = {100, 200, 300, 400, 500};
int *pa = a;
cout << *(pa + 4);
Starea Memoriei:

Pointerul pa pointează către începutul vectorului a (adică &a[0]).

Expresia *(pa + 4) accesează elementul de la indicele 4, adică al 5-lea element din vector: 500.

Exercițiul 8: Operații încrucișate cu pointeri Mediu

Care vor fi valorile finale afișate pentru a și b?

int a = 2, b = 5;
int *pa = &a, *pb = &b;
*pa += *pb;
*pb += *pa;
cout << a << " " << b;
Calcul Pas-cu-Pas:

1. *pa += *pb ➔ a = a + b ➔ a = 2 + 5 = 7.

2. *pb += *pa ➔ b = b + a (folosind noua valoare a lui a) ➔ b = 5 + 7 = 12.

Afișajul final va fi: 7 12.