Pentru că am introdus variabilele și constantele, putem începe să operăm cu ele folosind operatori. Ceea ce urmează este o listă completă a operatorilor. În acest moment nu este necesar să îi cunoaștem pe toți, dar i-am prezentat pe toți pentru a ne servi ca referință.
Operatorul de atribuire asignează unei variabile o valoare.
1 | x = 5; |
Această instrucțiune atribuie valoarea întreagă 5
variabilei x
. Operația de atribuire are loc întotdeauna de la dreapta la stânga, niciodată în sens invers:
1 | x = y; |
Această instrucțiune atribuie variabilei x
valoarea conținută în variabila y
. Valoarea lui x
la momentul execuției acestei instrucțiuni este pierdută și înlocuită cu valoarea lui y
.
De asemenea, considerăm că doar atribuim lui x
valoarea lui y
, la momentul operației de atribuire. De aceea, dacă y
se schimbă mai târziu, aceasta nu va afecta valaorea luată de x
.
De exemplu, să ne uităm puțin la codul următor – am inclus în comentarii evoluția conținutului memorat în variabile:
| // operatorul de atribuire #include <iostream> using namespace std; int main () { int a, b; // a:?, b:? a = 10; // a:10, b:? b = 4; // a:10, b:4 a = b; // a:4, b:4 b = 7; // a:4, b:7 cout << "a:"; cout << a; cout << " b:"; cout << b; } | a:4 b:7 |
Edit & run on cpp.sh
Acest program afișează pe ecran valorile finale ale lui a
și b
(4, respectiv 7). Observați că a
nu a fost afectat de schimbarea finală a lui b
, chiar dacă am avut a = b
mai înainte.
Operațiile de atribuire sunt expresii care pot fi evaluare. Aceasta înseamnă că atribuirea însăși are o valoare și, pentru tipurile fundamentale, este cea atribuită în operație. De exemplu:
1 | y = 2 + (x = 5); |
În această expresie, lui y
i se atribuie rezultatul sumei dintre 2 și valoarea altei expresii de atribuire (care are, la rândul ei, valoarea 5). Este echivalentă cu:
1 | x = 5; y = 2 + x; |
cu rezultatul final 7 atribuit lui y
.
Următoarea expresie este validă, de asemenea, C++:
1 | x = y = z = 5; |
Ea asignează valoarea 5 tuturor celor trei variabile: x
, y
și z
; întotdeauna de la dreapta la stânga.
Cele cinci operații aritmetice suportate de C++ sunt:
Operator | Descriere |
---|---|
+ | Adunare |
- | Scădere |
* | Înmulțire |
/ | Împărțire |
% | Modulo |
Operațiile de adunare, scădere, înmulțire și împărțire corespund exact operatorilor matematici cunoscuți. Ultimul, operatorul modulo, reprezentat de simbolul procent (%
), determină restul împărțirii a două valori. De exemplu:
1 | x = 11 % 3; |
are ca efect faptul că variabila x
conține valoarea 2, deoarece împărțind pe 11 la 3 obținem câtul 3 și restul 2.
Operatorii pentru atribuire compusă modifică valoarea curentă a variabilei față de ea însăși. Sunt echivalente cu atribuirea rezultatului unei operații chiar primului operand:
Expresie | Echivalentă cu… |
---|---|
y += x; | y = y + x; |
x -= 5; | x = x - 5; |
x /= y; | x = x / y; |
pret *= cantitate + 1; | pret = pret * (cantitate+1); |
și la fel pentru toți operatorii de atrbuire compusă. De exemplu:
1 | // atribuire compusa #include <iostream> using namespace std; int main () { int a, b=3; a = b; a+=2; // echivalent cu a=a+2 cout << a; } | 5 |
Unele expresii pot fi prescurtate chiar mai mult: operatorul de incrementare (++
) și operatorul de decrementare (--
) crește, respectiv descrește cu o unitate valoarea memorată în variabilă. Ele sunt echivalente cu +=1
, respectiv -=1
. Deci:
1 | ++x; x+=1; x=x+1; |
au toate același sens; fiecare dintre ele crește cu 1 valoarea lui x
.
În primele compilatoare C, cele trei expresii de mai sus ar fi putut produce cod executabil diferit. Acum, însă, acest tip de optimizare a codului este executat automat de către compilator, deci cele trei expresii ar trebui să producă exact același cod executabil.
O particularitate a acestui operator este aceea că poate fi folosit atât ca prefix, cât și ca sufix. Aceasta înseamnă că poate fi scris fie înaintea numelui variabile(++x
) fie după el (x++
). Cu toate că în expresii simple precum x++
sau ++x
, au exact același înțeles, în alte expresii în care rezultatul incrementării sau decrementării este evaluat, poate fi o mare diferență între sensurile lor: în cazul prefixării operatorului de incrementare a valorii (++x
), expresia se evaluează cu valoarea finală a lui x
, adică acea valoare care a fost deja majorată. Pe de altă parte, în cazul postfixării (x++
), valoarea este majorată,dar expresia se evaluează cu valaorea pe care o avea x înainte de incrementare. Să observăm diferența:
Exemplul 1 | Exemplul 2 |
---|---|
x = 3; | x = 3; |
În Exemplul 1, valoarea asignată lui y
este valoarea lui x
după ce a fost majorată. În timp ce în Exemplul 2, are valoarea lui x
înainte ca ea să fi fost majorată.
Două expresii pot fi comparate folosind operatori de relație și de egalitate: de exemplu, pentru a ști dacă două valori sunt egale sau dacă una este mai mare decât cealaltă.
Rezultatul unei asemenea operații este una dintre valorile boolene true (adevărat) sau false (fals).
Operatorii relaționali C++ sunt:
Operator | Descriere |
---|---|
== | Egal cu |
!= | Diferit de |
< | Mai mic decât |
> | Mai mare decât |
<= | Mai mic decât sau egal cu |
>= | Mai mare decât sau egal cu |
Să vedem câteva exemple:
1 | (7 == 5) // are valoarea false (5 > 4) // are valoarea true (3 != 2) // are valoarea true (6 >= 6) // are valoarea true (5 < 5) // are valoarea false |
Evident că nu doar valori numerice constante pot fi comparate, ci oricare două valori, inclusiv variabile. Să presupunem că a=2
, b=3
și c=6
; atunci:
1 | (a == 5) // are valoarea false, deoarece a nu este egal cu 5 (a*b >= c) // are valoarea true, deoarece (2*3 >= 6) este true (b+4 > a*c) // are valoarea false, deoarece (3+4 > 2*6) este false ((b=2) == a) // are valoarea true |
Atenție! Operatorul de atribuire (operatorul =
, cu un simbol egal) nu este același cu operatorul de egalitate folosit pentru comparație(operatorul ==
, cu două semne egal); primul (=
) atribuie valoarea din partea dreaptă variabilei din stânga, în timp ce celălalt (==
) compară valorile din cele două părți ale operatorului de egalitate. De aceea, în ultima expresie ((b=2) == a
), mai întâi atribuim valoarea 2
lui b
și apoi o comparăm cu a
(care conține tot valoarea 2), deci avem true
.
Operatorul !
este implementarea în C++ a operației boolene NOT. Are doar un operand, la dreapta sa, și îl neagă producând false
dacă operandul este true
, respectiv true
dacă operandul este false
. În principiu, el returnează valoarea booleană opusă valorii pe care o are operandul. De exemplu:
1 | !(5 == 5) // are valoarea false deoarece expresia din dreapta (5 == 5) este true !(6 <= 4) // are valoarea true deoarece (6 <= 4) este false !true // are valoarea false !false // are valoarea true |
Operatorii logici &&
și ||
se folosesc la evaluarea a două expresii pentru a obține un singur rezultat de relație. Operatorul &&
corespunde operației logice boolene AND, care va avea rezultatul true
dacă ambii operanzi au valoarea true
și false
în celelalte situații. Următorul tabel ne arată rezultatul operatorului &&
după evaluarea expresiei a&&b
:
Operatorul && (și) | ||
---|---|---|
a | b | a && b |
true | true | true |
true | false | false |
false | true | false |
false | false | false |
Operatorul ||
corespunde operației logice boolene OR, care are valaorea true
dacă oricare dintre operanzii săi are valoarea true
, deci va fi falsă numai când ambii operanzi sunt falși. Iată posibilele rezultate ale lui a||b
:
Operatorul || (sau) | ||
---|---|---|
a | b | a || b |
true | true | true |
true | false | true |
false | true | true |
false | false | false |
De exemplu:
1 | ( (5 == 5) && (3 > 6) ) // are valoarea false ( true && false ) ( (5 == 5) || (3 > 6) ) // are valoarea true ( true || false ) |
Când folosim operatorii logici, C++ evaluează numai cât este necesar de la stânga spre dreapta pentru a afla rezultatul operației, ignorând restul. De aceea, în ultimul exemplu ((5==5)||(3>6)
), C++ evaluează mai întâi dacă egalitatea 5==5
este true
și , în caz afirmativ, nu va mai verifica dacă și inegalitatea 3>6
este true
sau nu. Acest mecanism este cunoscut ca evaluare scurt-circuit și lucrează, pentru acești operatori ca mai jos:
Operator | Scurt-circuit |
---|---|
&& | dacă expresia din partea stângă este false , rezultatul combinat este false (expresia din partea dreaptă nu va mai fi evaluată). |
|| | dacă expresia din partea stângă este true , rezultatul expresiei combinate este true (expresia din partea dreaptă nu va mai fi evaluată). |
Cel mai important este când expresia din partea dreaptă ar putea avea efecte, ca de exemplu să altereze valorile:
1 | if ( (i<10) && (++i<n) ) { /*...*/ } // atentie la expresia care il incrementeaza pe i |
Aici, expresia condițională combinată l-ar putea crește pe i
cu o unitate, dar numai în cazul în care condiția din stânga semnului &&
are valaorea true
, deoarece altfel condiția din partea dreaptă (++i<n
) nu va fi evaluată (deci incrementarea nu are loc).
Operatorul condițional evaluează o expresie, returnând o valoare dacă expresia are valoarea true
, respectiv o altă valoare atunci când expresia are valoarea de adevăr false
. Sintaxa ei este:
conditie ? rezultat_1 : rezultat_2
În cazul în care conditie
are valoarea true
, întreaga expresie se evaluează cu rezultat_1
, iar altfel se evaluează cu rezultat_2
.
1 | 7==5 ? 4 : 3 // are valoarea 3, deoarece 7 nu este egal cu 5. 7==5+2 ? 4 : 3 // are valoarea 4, deoarece 7 este egal cu 5+2. 5>3 ? a : b // are valoarea lui a, deoarece 5 este mai mare decat 3. a>b ? a : b // are acea valoare care este mai mare, a sau b. |
De exemplu:
1 | // operatorul conditional #include <iostream> using namespace std; int main () { int a,b,c; a=2; b=7; c = (a>b) ? a : b; cout << c << '\n'; } | 7 |
Edit & run on cpp.sh
În acest exemplu, a
este 2, b
este 7, așa încât expresia care trebuie evaluată (a>b
) nu are valoarea true
, deci prima valoare precizată după semnul de întrebare este ignorată în favoarea celei de-a doua valori (cea de după două puncte) adică b
(care este 7).
Operatorul virgulă (,
) este folosit pentru a separa două sau mai multe expresii succesive. Când setul de expresii trebuie evaluat la o valoare, numai expresia cea mai din dreapta se va lua în considerare.
De exemplu, codul următor:
1 | a = (b=3, b+2); |
asignează mai întâi valoarea 3 lui b
, apoi asignează b+2
variabilei a
. Așa încât, la sfârșit, variabila a
ar putea conține valoarea 5 în timp ce variabila b
ar conține valoarea 3.
Operatorii pe biți modifică variabilele considerând șablonul de biți al valorilor pe care le conțin variabilele.
Operator | Echivalent asm | Descriere |
---|---|---|
& | AND | AND pe biți |
| | OR | OR inclusiv pe biți |
^ | XOR | OR exclusiv pe biți |
~ | NOT | Complement unar (complementarea pe biți) |
<< | SHL | Shiftare spre stânga pe biți |
>> | SHR | Shiftare spre dreapta (pe biți) |
Operatorii de conversie de tip permit conversia unei valori dintr-un anumit tip de dată la un al tip. Sunt câteva modalități de a face aceasta în C++. Cea mai simplă, care a fost moștenită din limbajul C, este cea prin care expresia de convertit este precedată de noul tip cuprins între paranteze (()):
1 | int i; float f = 3.14; i = (int) f; |
Codul anterior convertește numărul real zecimal 3.14
la o valoare întreagă (3
); restul se pierde. Aici, operatorul de conversie este (int)
. Altă modalitate de a face exact același lucru în C++ este folosirea notației funcționale: după cuvântul cheie corespunzător noului tip, urmează expresia de convertit cuprinsă între paranteze:
1 | i = int (f); |
Ambele modalități de conversie de tip sunt valide în C++.
Acest operator acceptă un parametru, care poate fi un tip de dată sau o variabilă, și returnează dimensiunea în bytes a acelui tip sau obiect:
1 | x = sizeof (char); |
Aici, lui x
i se asignează valoarea 1
, deoarece tipul de dată char
are dimensiunea de un byte.
Valoarea returnată de sizeof
este determinată în timpul compilării, deci ea este determinată întotdeauna înainte de execuția programului.