Operatori

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 (=)

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

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
2
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.

Operatori aritmetici ( +, -, *, /, % )

Cele cinci operații aritmetice suportate de C++ sunt:

OperatorDescriere
+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.

Atribuire compusă (+=, -=, *=, /=, %=, >>=, <<=, &=, ^=, |=)

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:

ExpresieEchivalentă 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
2
3
4
5
6
7
8
9
10
11
// 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

Incrementare și decrementare (++, --)

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
2
3
++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 1Exemplul 2
x = 3;
y = ++x;
// x contine 4, y contine 4
x = 3;
y = x++;
// x contine 4, y contine 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ă.

Operatori de relație și egalitate ( ==, !=, >, <, >=, <= )

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:

OperatorDescriere
==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
2
3
4
5
(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
2
3
4
(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.

Operatori logici ( !, &&, || )

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
2
3
4
!(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)
aba && b
truetruetrue
truefalsefalse
falsetruefalse
falsefalsefalse

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)
aba || b
truetruetrue
truefalsetrue
falsetruetrue
falsefalsefalse

De exemplu:
1
2
( (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:

OperatorScurt-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 ternar ( ? )

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
2
3
4
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
2
3
4
5
6
7
8
9
10
11
12
13
14
// 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

Î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ă ( , )

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.

Operatori pe biți ( &, |, ^, ~, <<, >> )

Operatorii pe biți modifică variabilele considerând șablonul de biți al valorilor pe care le conțin variabilele.

OperatorEchivalent asmDescriere
&ANDAND pe biți
|OROR inclusiv pe biți
^XOROR exclusiv pe biți
~NOTComplement unar (complementarea pe biți)
<<SHLShiftare spre stânga pe biți
>>SHRShiftare spre dreapta (pe biți)

Operatorul de conversie explicită

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
2
3
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++.

sizeof

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.

Alți operatori

Mai târziu, în acest tutorial vom vedea mai mulți operatori, precum cei referitori la pointeri sau cei specifici programării orientate pe obiecte.

Precedența operatorilor

O singură expresie poate conține mai mulți operatori. De exemplu:

1
x = 5 + 7 % 2;

În C++, expresia de mai sus atribuie valoarea 6 lui x, deoarece operatorul % are o precedență mai mare față de operatorul + și este evaluat întotdeauna înainte. Uneori părți ale unor expresii pot fi cuprinse între paranteze pentru a modifica ordinea dată de precedență sau pentru a face mai explicit efectul dorit. Să observăm diferența:

1
2
x = 5 + (7 % 2);    // x = 6 (la fel si fara paranteze)
x = (5 + 7) % 2;    // x = 0 

De la prioritatea cea mai mare la cea mai mică, operatorii C++ sunt evaluați în ordinea următoare:
Gradgrup de precedențăOperatorDescriereGrupare
1Domeniu::Calificator de domeniuDe la stânga la dreapta
2Postfixat (unar)++ --Incrementare / decrementare postfixatăDe la stânga la dreapta
()Forme funcționale
[]subscript
. ->Accesare membru
3Prefixat (unar)++ --Incrementare / decrementare prefixatăDe la dreapta la stânga
~ !NOT pe biți / NOT logic
+ -Unar prefixat
& *Referențiere / Dereferențiere
new deleteAlocare / Dealocare
sizeofparameter pack
(type)Conversie de tip în stilul C
4Pointer la membru.* ->*Pointer de accesDe la stânga la dreapta
5Aritmetic: scaling* / %înmulțire, împărțire, moduloDe la stânga la dreapta
6Aritmetic: adunare+ -adunare, scădereDe la stânga la dreapta
7Deplasare pe biți<< >>deplasare stânga, deplasare dreaptaDe la stânga la dreapta
8Relațional< > <= >=Operatori de comparațieDe la stânga la dreapta
9Egalitate== !=egalitate / inegalitateDe la stânga la dreapta
10Și&AND pe bițiDe la stânga la dreapta
11OR exclusiv^XOR pe bițiDe la stânga la dreapta
12OR inclusiv|OR pe bițiDe la stânga la dreapta
13Conjuncție&&AND logicDe la stânga la dreapta
14Disjuncție||OR logicDe la stânga la dreapta
15Expresii la nivel de atribuire= *= /= %= += -=
>>= <<= &= ^= |=
Atribuire / Atribuire compusăDe la dreapta la stânga
?:Operator condițional
16Secvență,Separator virgulăDe la stânga la dreapta

Când o expresie are doi operatori cu același grad de precedență, gruparea determină care dintre ei este evaluat primul: fie de la stânga la dreapta fie de la dreapta la stânga.

Includerea tuturor subexpresiilor în paranteze (chiar și acolo unde nu este necesar datorită precedenței) poate îmbunătăți claritatea sursei.
Index
Index