Curs C++ | Sectiunea 25 – Conversii
💡 O conversie este procesul prin care schimbam natura unei date fara a-i schimba (daca este posibil) valoarea. Unul din cele mai simple exemple de conversie ese schimbarea tipului de date.
Literalul valorii 1 de tip int este convertit la acelasi tip long precum variabila data. Acest lucru presupune ca reprezentarea interna a datelor va suferi o schimbare (in acest caz particular, al numarului de biti folositi pentru stocarea valoarii, ce va fi modificat) dar valoarea insasi ramane neschimbata.
Putem evita conversia prin specificarea mai clara in cod a literalului. Spre exemplu, putem adauga sufixul ‘L‘ (sau ‘l‘ – fiind echivalente) ce marcheaza faptul ca literalul este definit explicit ca long.
Ajungem asfel la concluzia ca toate tipurile de conversii pot fi impartite in doua categorii:
- conversii automate ce sunt realizate fara voia noastra de catre compilator, acesta stiind unde este nevoie sa fie aplicate; mai pot fi numite si conversii implicite
- conversii explicite ce sunt realizate de catre noi folosind codul scris; compilatorul se va supune dorintei noastre si va converti datele corespunzator; acest tip de conversie este deseori numita typecasting
Conversii Implicite
❗ Asa cum am mai discutat, conversiile implicite pot aparea fara interventia noastra. Compilatorul decide unde si cand ar trebui realizate. Bineinteles, trebuie sa fim constienti de ele, sa fim capabili sa gasim toate cazurile in care compilatorul ne poate converti datele.
Acestea afecteaza datele tipurilor fundamentale si sunt in general asociate cu schimbarea reprezentarii interne. Sa trecem prin cateva cazuri in care conversiile implicite joaca un rol important, desi la prima vedere invizibil:
- o valoarea este folosita ca parte a unei expresii complexe construita din multiple valori de diferite tipuri (exemplul 1: variabila short este convertita in int)
- o valoarea joaca rolul unei conditii logice intr-o instructiune, precum if, while etc (exemplul 2: variabla double este convertita in int)
- valoarea este supusa atribuirii si este folosita pentru:
- schimbarea valorii variabilei (exemplul 3: int este convertit in float)
- setarea valorii unui parametru formal (exemplul 4: parametrul efectiv de tip float este convertit in parametrul formal de tip int)
- specifica valaora returnata de o functie (exemplul 5: valoarea de tip int returnata de functie are ca tip de returnare un float)
Conversii Explicite
In general, C++ ne ofera doua moduri in care le putem realiza. Prima poarta numele de C-syle casting (dupa cum ii spune si numele, fiind prezenta de la predecesorul nostru C), si are o sintaxa de forma urmatoare:
A doua varianta poarta numele de notatie functionala (functional notation) care este o sintaxa nativa pentru C++, nefiind existenta si in C. In acest caz, numele noului tip este tratat ca o functie iar sintaxa este de felul urmator:
💡 Ambele variante sunt la fel cand le folosim impreuna cu valori de tipuri standard, dar notatia functionala poate fi folosita si cu obiecte, putand astfel sa avem mai mult de o valoare. De mentionat ar mai fi ca acestea nu sunt singurele variante, dar vom mai discuta mai tarziu despre asta.
Castig & Pierdere
❗ De fiecare data cand o conversie are loc, compilatorul face tot posibilul sa pastreze valoarea originala, dar acest lucru nu este mereu posibil. Vom parcurge cateva exemple ce demonstreaza aceasta pierdere a acuratetii.
🦸♂️Un scenariu bun se intampla atunci cand lungimea memoriei folosita pentru reprezentare ramane aceeasi sau creste. In acest caz putem fi siguri ca valoarea originala va ramane intacta.
🙅♂️ Acum sa aruncam o privire si pe un scenariu opus celui precedent. Incercam sa transferam valoarea maxima posibila a unui int unei variabile de tip short. Puteti si afisa valoarea dupa conversie daca sunteti curiosi cum va arata 🙂 .
🗿 Alt exemplu pe care il putem discuta este conversia de la un float la un int. Stim deja ca acest lucru presupune pierderea acuratetii, pierzand partea fractionala a valorii. Putem insa, daca valoarea de tip float este suficient de mare (sau foarte mica), sa suferim si o pierdere a valorii. Acest lucru se aplica valorilor ce se afla in afara domeniului (scope) unui intreg.
Promotion
💡 Pentru evitarea ambelor tipuri de pierdere, compilatorul foloseste o strategie numita promovare (promotion). Acest lucru presupune ca in momentul unei conversii, datele sunt evaluate la cel mai sigur tip.
Spre exemplu, cand un int si un short sunt folosite in aceeasi expresie, ne putem astepta ca valoarea cu un interval mai restrans (short in acest caz) sa fie promovata (promoted) la tipul cu intervalul cel mai larg (int), astfel fiind evitata pierderea valorii.
In mod similar se va intampla si cand avem de a face cu un float si un double, valoarea float va fi promovata la una de tip double.
❗ Toate promovarile sunt realizate dupa urmatorul set de reguli. Regulile sunt aplicate in ordinea de mai jos pana ce toate datele dintr-o expresie au acelasi tip !
- datele de tip char sau short int vor fi convertite la int (integer promotion)
- datele de tip float sufera o conversie la double (floating point promotion)
- daca exista orice valoare de tip double in expresie, celelalte date vor fi convertite la double
- daca exista orice valoare de tip long int in expresie,celelalte date vor fi convertite la long int
Daca in contextul in care este calculata expresia este nevoie de alt tip decat cel rezultat in urma conversiei, atunci ultima conversie va fi de tipul necesar contextului.
Un exemplu practic
Vom analiza urmatorul exemplu pas cu pas pentru a intelege ordinea in care au loc aceste promovari.
- Promovarea este prima care se intampla, rezultand:
- Suma celor 3 variabile de tip short, char si float vor fi convertite in double:
- Suma finala va fi calculata ca un double, dar din cauza contextului (reprezentand tipul argumentului din stanga operatorului de asignare) care este de tip int, va fi realizata o alta conversie la int, expresia finala aratand astfel:
Aici se termina si aceasta sectiune 🙂 . Daca aveti intrebari suplimentare puteti folosi informatiile de aici.
➡ Sectiunea anterioara:Curs C++ | Sectiunea 24 – Siruri de pointeri
➡ Sectiunea urmatoare:Curs C++ | Sectiunea 26 – Strings (Bazele)

