> For the complete documentation index, see [llms.txt](https://ase.lucianvilcea.ro/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://ase.lucianvilcea.ro/home/programare-orientata-obiect/recapitulare-c++/tipuri-constante-pointeri.md).

# Tipuri, constante, pointeri

Pointerii în C++ devin cu adevărat interesanți atunci când introducem în ecuație și cuvântul cheie `const`. Deși poate părea complicat la prima vedere, odată ce înțelegi logica din spatele fiecărei combinații, totul devine simplu. Să explorăm fiecare caz în parte, cu exemple concrete și diagrame care ilustrează exact ce se întâmplă în memorie. În cadrul acestor exemple, vom folosi ca exemplu tipul `char`, însă aceleași tehnici pot fi extrapolate și pentru restul tipurilor primitive (și nu numai) din C++.

Pentru o mai simplă reprezentare a datelor în memorie, am folosit următoarea convenție:

* **forme**:
  * **pătrat**: variabilă
  * **hexagon**: pointer
* **culori**:
  * **albastru**: variabilă mutabilă
  * **portocaliu**: variabilă constantă
* **bordurile pointerilor**:
  * **linie plină**: pointerul este declarat ca indicând o variabilă mutabilă
  * **linie punctată**: pointerul este declarat ca indicând spre o constantă

Terminologie:

* **variabilă** - zonă de memorie identificată prin nume, folosită pentru a stoca o valoare ce poate fi modificată
* **constantă** - zonă de memorie identificată prin nume, folosită pentru a stoca o valoare ce nu poate fi modificată
* **pointer** - variabilă folosită pentru a stoca adresa unei alte zone de memorie (a unei variabile sau constante), care poate fi atât variabil, cât și constant
* **mutabil** - caracterul unei variabile de a putea fi modificată după ce a fost declarată
* **imutabil** - caracterul unei variabile de a nu putea fi modificată după ce a fost declarată

### Variabile simple: Fundamentele

Când declarăm o variabilă obișnuită, de exemplu `char c = 'A'`, creăm un spațiu în memoria stack care stochează valoarea caracterului 'A'. Această variabilă are o adresă în memorie, iar noi putem modifica valoarea ei oricând dorim. Dacă apoi schimbăm valoarea lui `c` în 'B', valoarea se modifică, dar adresa rămâne aceeași. Iată o secvență de cod care declară o variabilă de tip `char` și îi atribuie o valoare.

```cpp
char c = 'A';

cout << "Caracterul este: " << c << endl;
cout << "Caracterul este stocat la adresa: " << static_cast<void*>(&c) << endl; 
```

```
Output:
> Caracterul este: A
> Caracterul este stocat la adresa: 00B6F823
```

Instrucțiunile de mai sus alocă o variabilă numită `c` la o adresă de memorie din stack, conform figurii de mai jos.

<figure><img src="https://2341277153-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FDZQFKa1I5bTOOhuhKP3Y%2Fuploads%2Fgbeb77wRA5vce1VNWnaa%2Ftype.png?alt=media&amp;token=7872cb91-fb04-4a56-9b18-8c3f957b2316" alt=""><figcaption></figcaption></figure>

Cele două instrucțiuni afișază valoarea variabilei, precum și adresa la care este alocată aceasta. Următoarele instrucțiuni modifică valoarea aceleiași variabile.

```cpp
c = 'B';

cout << "Caracterul este: " << c << endl;
cout << "Caracterul este stocat la adresa: " << static_cast<void*>(&c) << endl;
```

```
Output:
> Caracterul este: B
> Caracterul este stocat la adresa: 00B6F823
```

Observăm cum, în urma executării acestor instrucțiuni, valoarea variabilei `c` s-a schimbat, însă adresa ei a rămas aceeași, precum în reprezentarea de mai jos.

<figure><img src="https://2341277153-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FDZQFKa1I5bTOOhuhKP3Y%2Fuploads%2FNJw75gZE5eh6iiw0EWBS%2Ftype2.png?alt=media&amp;token=cf51ffd6-c4cb-415b-b565-c71b4e38d75b" alt=""><figcaption></figcaption></figure>

În acest caz, avem libertate totală. Valoarea poate fi modificată oricând, iar memoria ocupată de variabilă rămâne la aceeași adresă pe toată durata vieții sale.

### Constante: Valori imutabile

Atunci când adăugăm `const` în fața declarației unui tip, de exemplu `const char c = 'A'`, transformăm variabila într-o constantă. Aceasta înseamnă că, odată ce am stabilit valoarea inițială, nu o mai putem schimba niciodată. Compilatorul va refuza orice încercare de modificare, generând o eroare. Este un mecanism de siguranță care ne protejează de modificări accidentale ale valorilor care ar trebui să rămână fixe.

```cpp
const char c = 'A';

cout << "Caracterul constant este: " << c << endl;
cout << "Caracterul constant este stocat la adresa: " << static_cast<const void*>(&c) << endl << endl;
```

```
Output:
> Caracterul constant este: A
> Caracterul constant este stocat la adresa: 00AFFCCB
```

Asemenea alocării unei variabile obișnuite (non-constante), se alocă în memorie o locație nouă care reține valoarea 'A', conform figurii de mai jos.

<figure><img src="https://2341277153-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FDZQFKa1I5bTOOhuhKP3Y%2Fuploads%2FVZkBNQFwbetckUXpvGmT%2Fconstant.png?alt=media&amp;token=a27c747d-c0ba-4186-b765-57f8290e2e96" alt=""><figcaption></figcaption></figure>

Însă, încercarea de a executa o instrucțiune precum cea de mai jos, generează eroare:

```cpp
c = 'B';
```

Deoarece variabila `c` este declarată ca fiind constantă, nu este permisă modificarea ei după ce atribuirea valorii inițiale a avut loc. Mai concret, odată stabilită, valoarea este blocată pentru întreg ciclul de viață al variabilei.

### Pointeri simpli către variabile modificabile

Lucrurile devin mai interesante când introducem pointerii. Un pointer este, în esență, o variabilă care stochează adresa altei variabile. Când declarăm `char* p = &c`, creăm un pointer care reține adresa caracterului `c`. Acum avem două modalități de a accesa caracterul: direct prin `c` sau indirect prin `*p` (operatorul de dereferențiere).

```cpp
char c = 'A';
char* p = &c;

cout << "Caracterul (accesat direct) este: " << c << endl;
cout << "Caracterul este stocat la adresa: " << static_cast<void*>(&c) << endl;
cout << "Valoarea retinuta de pointer: " << static_cast<void*>(p) << endl;
cout << "Caracterul (accesat prin pointer) este: " << *p << endl;
cout << "Pointerul este stocat la adresa: " << &p << endl;
```

```
Output:
> Caracterul (accesat direct) este: A
> Caracterul este stocat la adresa: 00AFFCCB
> Valoarea retinuta de pointer: 00AFFCCB
> Caracterul (accesat prin pointer) este: A
> Pointerul este stocat la adresa: 00AFFCBC
```

În urma executării instrucțiunilor de mai sus, se alocă în memorie două variabile: una de tip `char`, denumită `c`, și alta de tip `char*`, denumită `p`, conform următoarei reprezentări.

<figure><img src="https://2341277153-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FDZQFKa1I5bTOOhuhKP3Y%2Fuploads%2FeXa6NtgYSZ37yC7bEkJP%2Fpointer1.png?alt=media&amp;token=95ea1ee9-62d3-4e09-915b-e232af590f06" alt=""><figcaption></figcaption></figure>

Observăm cum adresa lui `c` este memorată ca valoare a pointerului `p`, iar caracterul 'A' se poate afișa atât direct, prin intermediul variabilei `c`, cât și indirect, prin dereferențierea pointerului `p` (operatorul `*`).

Deoarece variabila `c` nu este constantă, aceasta permite modificarea valorii reținute în aceasta. Așadar, prin executarea blocului de cod de mai jos, se poate modifica valoarea variabilei (atât în mod direct, cât și prin dereferențiere).

```cpp
c = 'B'; 
//*p = 'B'; // alternativ, prin dereferențiere

cout << "Caracterul (accesat direct) este: " << c << endl;
cout << "Caracterul este stocat la adresa: " << static_cast<void*>(&c) << endl;
cout << "Valoarea retinuta de pointer: " << static_cast<void*>(p) << endl;
cout << "Caracterul (accesat prin pointer) este: " << *p << endl;
cout << "Pointerul este stocat la adresa: " << &p << endl << endl;
```

```
Output:
> Caracterul (accesat direct) este: B
> Caracterul este stocat la adresa: 00AFFCCB
> Valoarea retinuta de pointer: 00AFFCCB
> Caracterul (accesat prin pointer) este: B
> Pointerul este stocat la adresa: 00AFFCBC
```

Observăm că valoarea variabilei `c` se modifică, însă atât adresa variabilei `c`, cât și a pointerului `p`, rămân neschimbate. De aceea, adresa de memorie reținută de `p` rămâne aceeași, deoarece modificarea s-a executat peste conținutul variabilei `c`, precum este reprezentat mai jos. Aceasta demonstrează caracterul mutabil al variabilei de tip `char` în acest context.

<figure><img src="https://2341277153-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FDZQFKa1I5bTOOhuhKP3Y%2Fuploads%2FyHtjOVbR0S5RD5vKIdrq%2Fpointer2.png?alt=media&amp;token=2a198a96-c747-41c4-af21-87e19499b45f" alt=""><figcaption></figcaption></figure>

Totodată, și pointerul `p` are caracter mutabil. Astfel, se poate modifica și valoarea acestuia - concret, din moment ce pointerii rețin adrese, ei pot indica spre alte variabile de același tip. În blocul de cod de mai jos, pointerul `p` este instruit să indice spre variabila `d`.

```cpp
char d = 'D';

p = &d;
cout << "Caracterul (accesat direct) este: " << c << endl;
cout << "Caracterul este stocat la adresa: " << static_cast<void*>(&c) << endl;
cout << "Valoarea retinuta de pointer: " << static_cast<void*>(p) << endl;
cout << "Caracterul (accesat prin pointer) este: " << *p << endl;
cout << "Pointerul este stocat la adresa: " << &p << endl <<endl;
```

```
Output:
> Caracterul (accesat direct) este: D
> Caracterul este stocat la adresa: 0020F9B7
> Valoarea retinuta de pointer: 0020F9B7
> Caracterul (accesat prin pointer) este: D
> Pointerul este stocat la adresa: 00AFFCBC
```

Se poate observa cum variabila `d`, stocată la adresa 0020F9B7 și care reține valoarea 'D', este acum referențiată de către pointerul `p`. Astfel, adresa reținută în acesta este înlocuită cu adresa variabilei `d`, precum în figura de mai jos.

<figure><img src="https://2341277153-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FDZQFKa1I5bTOOhuhKP3Y%2Fuploads%2FKwln65CWug4tc8P0sbIa%2Fpointer3.png?alt=media&amp;token=382b6b42-ebfd-4389-bcd4-89b710e5f814" alt=""><figcaption></figcaption></figure>

În această situație, am demonstrat că, atât valoarea variabilei de tip `char`, cât și pointerul către aceasta, își pot modifica valorile.

### Pointeri către constante: Protejarea valorilor

În cazul anterior, pointerul a indicat către o variabilă mutabilă. Există situații când avem nevoie ca aceștia să poată indica spre constante, însă păstrând flexibilitatea de a schimba spre ce variabilă indică. Astfel, când sintaxa este sub forma `const char* p`, declarăm un pointer către un caracter constant. Acest lucru înseamnă că nu putem modifica valoarea caracterului **prin intermediul pointerului**, însă putem modifica spre ce caracter indică pointerul. Să luăm instrucțiunile de mai jos:

```cpp
const char c = 'A';
const char* p = &c;

cout << "Caracterul (accesat direct) este: " << c << endl;
cout << "Adresa caracterului: " << static_cast<const void*>(&c) << endl;
cout << "Valoarea pointerului (adresa catre caracter): " << static_cast<const void*>(p) << endl;
cout << "Caracterul (accesat prin pointer) este: " << *p << endl;
cout << "Adresa pointerului: " << &p << endl;
```

```
Output:
> Caracterul (accesat direct) este: A
> Adresa caracterului: 0020F9B7
> Valoarea pointerului (adresa catre caracter): 0020F9B7
> Caracterul (accesat prin pointer) este: A
> Adresa pointerului: 0020F9A8
```

Observăm că am alocat o constantă `c`, căreia i-am atribuit valoarea 'A'. Deși întâlnim cuvântul cheie `const` în definiția pointerului `p`, acesta se referă la tipul variabilei spre care indică, și nu face pointerul în sine constant. Astfel, memoria alocată în acest caz este reprezentată mai jos.

<figure><img src="https://2341277153-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FDZQFKa1I5bTOOhuhKP3Y%2Fuploads%2F7Qka4HUWVItmq4GejrQx%2FpointerToConstant1.png?alt=media&amp;token=64615d52-c666-4f88-b02f-f4a68332d4c7" alt=""><figcaption></figcaption></figure>

Deoarece valoarea variabilei `c` este constantă, instrucțiuni precum cea de mai jos generează eroare, nefiind posibilă modificarea variabilei.

```cpp
c = 'B';
```

Totuși, deoarece pointerul `p` nu este constant, avem posibilatea de a indica spre o altă constantă de același tip, precum în instrucțiunile de mai jos:

```cpp
const char d = 'D';
p = &d;

cout << "Caracterul d (accesat direct) este: " << d << endl;
cout << "Adresa lui d: " << static_cast<const void*>(&d) << endl;
cout << "Valoarea pointerului p: " << static_cast<const void*>(p) << endl;
cout << "Caracterul (accesat prin pointer) este: " << *p << endl;
cout << "Adresa pointerului p: " << &p << endl << endl;
```

```
Output:
> Caracterul d (accesat direct) este: D
> Adresa lui d: 0020F99F
> Valoarea pointerului p: 0020F99F
> Caracterul (accesat prin pointer) este: D
> Adresa pointerului p: 0020F9A8
```

În această situație, memoria este alocată astfel:

<figure><img src="https://2341277153-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FDZQFKa1I5bTOOhuhKP3Y%2Fuploads%2FefQhR3pF93WTwj3jlYoY%2FpointerToConstant2.png?alt=media&amp;token=4c6439c1-763f-467c-a487-9bcbf0ac08e9" alt=""><figcaption></figcaption></figure>

#### Pointer spre constantă căruia i se atribuie adresa unei variabile mutabile.

Există și o situație interesantă. După cum am menționat la începutul acestei secțiuni, un pointer către o constantă nu permite modificarea variabilei prin intermediul său, însă acest lucru nu impune obligativitatea ca pointerul să indice neapărat spre o constantă. Pot exista, astfel, și situații de acest tip:

```cpp
char e = 'E';
p = &e;

cout << "Caracterul d (accesat direct) este: " << e << endl;
cout << "Adresa lui d: " << static_cast<const void*>(&e) << endl;
cout << "Valoarea pointerului p: " << static_cast<const void*>(p) << endl;
cout << "Caracterul (accesat prin pointer) este: " << *p << endl;
cout << "Adresa pointerului p: " << &p << endl << endl;
```

```
Output
> Caracterul e (accesat direct) este: E
> Adresa lui e: 00CFFCCF
> Valoarea pointerului p: 00CFFCCF
> Caracterul (accesat prin pointer) este: E
> Adresa pointerului p: 0020F9A8
```

Deși variabila `e` nu este constantă, un pointer spre o constantă poate indica spre aceasta, deoarece semnificația termenului "constantă" se referă la caracterul imutabil al variabilei prin intermediul pointerului, nu al variabilei în sine. Așadar, memoria alocată în această situație poate fi reprezentată astfel:

<figure><img src="https://2341277153-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FDZQFKa1I5bTOOhuhKP3Y%2Fuploads%2FeptePhbxl2Cja2HLSeoe%2FpointerToConstant3.png?alt=media&amp;token=e3d63a47-a3ac-4b96-a7cd-cd96a514bca2" alt=""><figcaption></figcaption></figure>

Din acest motiv, instrucțiuni precum cele de mai jos sunt perfect valabile:

```cpp
e = 'X';
cout << "Caracterul d (accesat direct) este: " << e << endl;
cout << "Adresa lui d: " << static_cast<const void*>(&e) << endl;
cout << "Valoarea pointerului p: " << static_cast<const void*>(p) << endl;
cout << "Caracterul (accesat prin pointer) este: " << *p << endl;
cout << "Adresa pointerului p: " << &p << endl << endl;
```

```
Output
> Caracterul e (accesat direct) este: X
> Adresa lui e: 00CFFCCF
> Valoarea pointerului p: 00CFFCCF
> Caracterul (accesat prin pointer) este: X
> Adresa pointerului p: 0020F9A8
```

Observăm că ambele adrese de memorie rămân neschimbate, schimbându-se doar valoarea reținută de variabila `e`, precum în figura de mai jos.

<figure><img src="https://2341277153-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FDZQFKa1I5bTOOhuhKP3Y%2Fuploads%2FqxytWRBbEpZr9i7gq6JF%2FpointerToConstant4.png?alt=media&amp;token=8dffe554-2c3b-4e94-8e52-ce7294589533" alt=""><figcaption></figcaption></figure>

Cu toate acestea, deși acum pointerul indică în esență spre o variabilă mutabilă, deoarece acesta este declarat ca pointer spre constantă, modificarea variabilei prin dereferențierea sa produce eroare:

```cpp
*p = 'Y';
```

În concluzie, pointerul spre constantă **nu implică faptul că variabila a cărei adresă este reținută în pointer este constantă, ci faptul că variabila spre care se indică are caracter imutabil atunci când este accesată prin dereferențiere.**

### Pointeri constanți către variabile: Legături permanente

Un pointer constant, declarat ca `char* const p = &c`, reprezintă cazul opus. Aici, pointerul în sine nu poate fi modificat după inițializare. El va indica mereu către aceeași variabilă. Cu toate acestea, putem modifica valoarea variabilei indicate, fie direct, fie prin dereferențiere. Exemplul de cod de mai jos exemplifică acest lucru.

```cpp
char c = 'A';
char* const p = &c;

cout << "Caracterul (accesat direct) este: " << c << endl;
cout << "Adresa caracterului: " << static_cast<const void*>(&c) << endl;
cout << "Valoarea pointerului (adresa catre caracter): " << static_cast<const void*>(p) << endl;
cout << "Caracterul (accesat prin pointer) este: " << *p << endl;
cout << "Adresa pointerului: " << &p << endl << endl;
}
```

```
Output:
> Caracterul (accesat direct) este: A
> Adresa caracterului: 00CFFCCF
> Valoarea pointerului (adresa catre caracter): 00CFFCCF
> Caracterul (accesat prin pointer) este: A
> Adresa pointerului: 00CFFCB4
```

Memoria alocată pentru instrucțiunile de mai sus poate fi reprezentată astfel:

<figure><img src="https://2341277153-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FDZQFKa1I5bTOOhuhKP3Y%2Fuploads%2Fpb0uj7IDkryvnzMVTNkA%2FconstantPointerToVariable1.png?alt=media&amp;token=6798af58-3fae-4966-bf65-74a8a30d7b00" alt=""><figcaption></figcaption></figure>

Deoarece pointerul indică spre o variabilă mutabilă, aceasta poate fi modificată atât direct, cât și prin dereferențiere, precum în exemplul de mai jos:

```cpp
c = 'B'; 
//*p = 'B'; // alternativ, prin dereferențiere

cout << "Caracterul (accesat direct) este: " << c << endl;
cout << "Adresa caracterului: " << static_cast<const void*>(&c) << endl;
cout << "Valoarea pointerului (adresa catre caracter): " << static_cast<const void*>(p) << endl;
cout << "Caracterul (accesat prin pointer) este: " << *p << endl;
cout << "Adresa pointerului: " << &p << endl << endl;
```

```
Output:
> Caracterul (accesat direct) este: B
> Adresa caracterului: 00CFFCCF
> Valoarea pointerului (adresa catre caracter): 00CFFCCF
> Caracterul (accesat prin pointer) este: B
> Adresa pointerului: 00CFFCB4
```

Modificările în memorie în această situație pot fi reprezentate astfel:

<figure><img src="https://2341277153-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FDZQFKa1I5bTOOhuhKP3Y%2Fuploads%2FGAHiTKPMn10EIzn5p82t%2FconstantPointerToVariable2.png?alt=media&amp;token=e30b14df-cb3b-4a85-b706-cfc90200aef4" alt=""><figcaption></figcaption></figure>

Totuși, deoarece de această dată pointerul este constant, instrucțiunile de mai jos vor genera eroare, deoarece, odată stabilită, adresa reținută în pointer nu mai poate fi modificată.

```cpp
char d = 'D';
p = &d;
```

### Pointeri constanți către constante: Imutabilitate completă

Cel mai restrictiv caz este cel în care, atât variabila spre care se indică, cât și pointerul, sunt tipuri constante, folosindu-se sintaxă de tipul `const char* const p`. Această instrucțiune declară un pointer constant care indică către un caracter constant. Nici pointerul nu poate fi redirecționat, nici valoarea caracterului nu poate fi modificată **prin dereferențiere**. Este maximum de protecție și imutabilitate.

```cpp
const char c = 'A';                 
const char* const p = &c; 

cout << "Caracterul (accesat direct) este: " << c << endl;
cout << "Adresa caracterului: " << static_cast<const void*>(&c) << endl;
cout << "Valoarea pointerului (adresa catre caracter): " << static_cast<const void*>(p) << endl;
cout << "Caracterul (accesat prin pointer) este: " << *p << endl;
cout << "Adresa pointerului: " << &p << endl << endl;
```

```
Output:
> Caracterul (accesat direct) este: A
> Adresa caracterului: 00CFFCCF
> Valoarea pointerului (adresa catre caracter): 00CFFCCF
> Caracterul (accesat prin pointer) este: A
> Adresa pointerului: 00CFFCB4
```

Memoria alocată în acest caz poate fi reprezentată astfel:

<figure><img src="https://2341277153-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FDZQFKa1I5bTOOhuhKP3Y%2Fuploads%2FET3nEl8DSOoWngIt5rAB%2FconstantPointerToConstant1.png?alt=media&amp;token=96f5076d-2ea5-4e6a-a2ea-4d69043a28ec" alt=""><figcaption></figcaption></figure>

La fel ca în situația pointerului la constantă, pointerul constant la variabilă constantă **nu se referă la faptul că tipul spre care indică pointerul trebuie să fie constant, ci că valoarea spre care pointerul indică nu poate fi modificată prin dereferențiere**. Astfel, următoarele instrucțiuni sunt permise.

```cpp
char c = 'A'; // caracter mutabil                
const char* const p = &c; // pointer constant la caracter constant

cout << "Caracterul (accesat direct) este: " << c << endl;
cout << "Adresa caracterului: " << static_cast<const void*>(&c) << endl;
cout << "Valoarea pointerului (adresa catre caracter): " << static_cast<const void*>(p) << endl;
cout << "Caracterul (accesat prin pointer) este: " << *p << endl;
cout << "Adresa pointerului: " << &p << endl << endl;
```

```
Output:
> Caracterul (accesat direct) este: A
> Adresa caracterului: 00CFFCCF
> Valoarea pointerului (adresa catre caracter): 00CFFCCF
> Caracterul (accesat prin pointer) este: A
> Adresa pointerului: 00CFFCB4
```

Observăm că, deși caracterul `c` nu este constant, C++ permite pointerului constant spre constantă acest tip de referențiere. Memoria, în acest caz, poate fi reprezentată astfel:

<figure><img src="https://2341277153-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FDZQFKa1I5bTOOhuhKP3Y%2Fuploads%2FOVG2lCf6tkeGrBnwWHJ2%2FconstantPointerToConstant2.png?alt=media&amp;token=8a21251e-de95-4ad5-8fa1-59dd3ef86ac0" alt=""><figcaption></figcaption></figure>

Deoarece variabila `c` este mutabilă, este permisă modificarea acesteia în mod direct, astfel:

```cpp
c = 'B';                

cout << "Caracterul (accesat direct) este: " << c << endl;
cout << "Adresa caracterului: " << static_cast<const void*>(&c) << endl;
cout << "Valoarea pointerului (adresa catre caracter): " << static_cast<const void*>(p) << endl;
cout << "Caracterul (accesat prin pointer) este: " << *p << endl;
cout << "Adresa pointerului: " << &p << endl << endl;
```

```
Output:
> Caracterul (accesat direct) este: B
> Adresa caracterului: 00CFFCCF
> Valoarea pointerului (adresa catre caracter): 00CFFCCF
> Caracterul (accesat prin pointer) este: B
> Adresa pointerului: 00CFFCB4
```

Putem astfel observa că modificarea variabilei prin accesare directă este posibilă, iar pointerul constant spre constantă se comportă identic. Memoria este modificată în urma acestor instrucțiuni astfel:

<figure><img src="https://2341277153-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FDZQFKa1I5bTOOhuhKP3Y%2Fuploads%2F3P6E0K63v9cjIUBcA4zK%2FconstantPointerToConstant3.png?alt=media&amp;token=bba8593b-223c-422d-a54a-451ae85457cb" alt=""><figcaption></figcaption></figure>

Totuși, o instrucțiuni precum cele de mai jos vor genera eroare:

```cpp
const char c = 'A'; // caracter constant                
const char d = 'D'; // caracter constant  
const char* const p = &c; // pointer constant la caracter constant

c = 'B' // Cazul 1
p = &d;    // Cazul 2

char e = 'E';
const char* const q = &e;
*q = 'X'; // Cazul 3
```

Astfel:

* în primul caz, variabila `c` este constantă și nu se poate modifica
* în al doilea caz, pointerul `p` nu poate indica spre o altă adresă, deoarece este constant
* în al treilea caz, se încearcă modificarea variabilei mutabile `e` prin dereferențiere, lucru nepermis de caracterul de pointer constant spre constantă al lui `q`.

### Rezumat

| Declarație            | Valoarea poate fi modificată direct?              | Valoarea poate fi modificată prin dereferențiere? | Pointerul poate fi redirecționat? |
| --------------------- | ------------------------------------------------- | ------------------------------------------------- | --------------------------------- |
| `char c`              | Da                                                | -                                                 | -                                 |
| `const char c`        | Nu                                                | -                                                 | -                                 |
| `char* p`             | Da                                                | Da                                                | Da                                |
| `const char* p`       | Da, dacă pointerul indică spre variabilă mutabilă | Nu                                                | Da                                |
| `char* const p`       | Da                                                | Da                                                | Nu                                |
| `const char* const p` | Da, dacă pointerul indică spre variabilă mutabilă | Nu                                                | Nu                                |

### Cum putem reține ușor sintaxa pentru toate aceste tipuri?

Există un truc simplu pentru a înțelege declarațiile cu pointeri și constante: citește-le de la dreapta la stânga, în engleză. De exemplu:

| Declarație            | Cum citim?                                                                                      |
| --------------------- | ----------------------------------------------------------------------------------------------- |
| `char c`              | c (`c`) is a character (`char`)                                                                 |
| `const char c`        | c (`c`) is a character (`char`) that's constant (`const`)                                       |
| `char* p`             | p (`p`) is a pointer (`*`) to a character (`char`)                                              |
| `const char* p`       | p (`p`) is a pointer (`*`) to a character (`char`) that's constant (`const`)                    |
| `char* const p`       | p (`p`) is a constant (`const`) pointer (`*`) to a character (`char`)                           |
| `const char* const p` | p (`p`) is a constant (`const`) pointer (`*`) to a character (`char`) that's constant (`const`) |

Înțelegerea acestor distincții este esențială pentru a scrie cod sigur și pentru a comunica intențiile tale ca programator. Fiecare combinație are scopul ei specific, iar alegerea corectă depinde de comportamentul pe care îl dorești în programul tău.


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter, and the optional `goal` query parameter:

```
GET https://ase.lucianvilcea.ro/home/programare-orientata-obiect/recapitulare-c++/tipuri-constante-pointeri.md?ask=<question>&goal=<endgoal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is optional and describes the broader end goal you are ultimately trying to accomplish on behalf of the user. GitBook uses it to tailor the answer towards what is most useful for that goal.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
