Ponderea si ordinea de evaluare
Tabelul de mai jos rezuma regulile de pondere si asociativi-
tate pentru toti operatorii, inclusiv pentru aceia pe care nu i-
am discutat inca. Operatorii de pe aceeasi linie au aceeasi
pondere; liniile sint in ordine de pondere descrescatoare,
astfel ca, de exemplu, "*", "/" si "%" au o a 646q1624g ceeasi pondere,
care este mai mare decit a lui "+" "-".
+----- ----- --------- ----- ------+----- ----- --------- ----- --------+
| () [] -> . | de la stinga la dreapta |
+----- ----- --------- ----- ------+----- ----- --------- ----- --------+
| ! ~ ++ -- - (tip) * & sizeof | de la dreapta la stinga |
+----- ----- --------- ----- ------+----- ----- --------- ----- -------+
| * / % | de la stinga la dreapta |
+----- ----- --------- ----- ------+----- ----- --------- ----- --------+
| + - | de la stinga la dreapta |
+----- ----- --------- ----- ------+----- ----- --------- ----- --------+
| << >> | de la stinga la dreapta |
+----- ----- --------- ----- ------+----- ----- --------- ----- --------+
| < <= > >= | de la stinga la dreapta |
+----- ----- --------- ----- ------+----- ----- --------- ----- --------+
| == != | de la stinga la dreapta |
+----- ----- --------- ----- ------+----- ----- --------- ----- --------+
| & | de la stinga la dreapta |
+----- ----- --------- ----- ------+----- ----- --------- ----- --------+
| ^ | de la stinga la dreapta |
+----- ----- --------- ----- ------+----- ----- --------- ----- --------+
| | | de la stinga la dreapta |
+----- ----- --------- ----- ------+----- ----- --------- ----- --------+
| && | de la stinga la dreapta |
+----- ----- --------- ----- ------+----- ----- --------- ----- --------+
| || | de la stinga la dreapta |
+----- ----- --------- ----- ------+----- ----- --------- ----- --------+
| ? : | de la dreapta la stinga |
+----- ----- --------- ----- ------+----- ----- --------- ----- --------+
+----- ----- --------- ----- ------+----- ----- --------- ----- --------+
| = += -= etc | de la dreapta la stinga |
+----- ----- --------- ----- ------+----- ----- --------- ----- --------+
| , (Capitolul 3) | de la stinga la dreapta |
+----- ----- --------- ----- ------+----- ----- --------- ----- --------+
Operatorii -> si. sint folositi pentru a accede membrii structuri-
lor; ei vor fi iscutati in Capitolul 6, impreuna cu sizeof (mari-
mea unui obiect). Capitolul 5 discuta * (indirectarea) si &
(adresa lui ...).
Sa notam ca ponderea operatorilor logici pe biti &, | si ^
este sub == i |=. Aceasta implica faptul ca expresiile care
testeaza biti, ca de exemplu
if (( x & MASK) == 0) ...
trebuie sa fie cuprinse in intregime intre paranteze, pentru a
da rezultatele steptate.
Asa cum am mentionat mai inainte, expresiile ce implica
operatori asociativi si comutativi (+, *, &, ^, |) pot fi
rearanjate chiar daca sint cuprinse in paranteze. In marea
majoritate a cazurilor, aceasta nu da diferente; in situatia
in care ar da, se pot folosi variabile temporare explicite
pentru a forta o ordine de evaluare particulara.
Limbajul C, ca si majoritatea celorlalte limbaje, nu specifica in
ce ordine se evalueaza operanzii unui operator. De exemplu, in
instructiuni de tipul
x = f() + g();
f poate fi evaluat inaintea lui g sau viceversa; deci,
daca sau f sau g altereaza o variabila externa de care depinde
si cealalta, x poate depinde de ordinea de evaluare. Din nou,
rezultatele intermediare pot fi stocate in variabile temporare
pentru a fi siguri de o anumita secventa.
In mod similar, ordinea in care sint evaluate argumentele
unei functii nu este specficata, asa ca instructiunea
printf("%d %d\n", ++n, power(2, n)); /* GRESIT */
poate (si o si face) produce rezultate diferite, pe diferite
calculatoare, depinzind de faptul daca n este incrementat sau nu
inainte de apelul lui power. Solutia, desigur, este sa scriem:
++n;
printf("%d %d\n", n, power(2, n));
Apelurile de functii, instructiunile de asignare imbricate,
operatorii de incrementare si decrementare provoaca "efecte secu-
ndare" - o anumita variabila este modificata ca un produs al
unei evaluari de expresie. In orice expresie implicind efecte
secundare, pot exista subtile dependente de ordinea in care sint
stocate variabilele ce iau parte in expresie. O situatie neferi-
cita este ilustrata de instructiunea:
a[i] = i++;
Chestiunea consta in a sti daca indicele este noua valoare a
lui i sau daca este vechea. Compilatorul poate face aceste
lucruri in moduri diferite, depinzind de interpretarea sa.
Cind efectele secundare (asignare la variabile efective) au loc,
sint lasate la discretia compilatorului, caci cea mai buna
ordine depinde puternic de arhitectura calculatorului.
Morala acestei discutii este aceea, ca scrierea de cod ce
depinde de ordinea de evaluare, este o proasta practica de
programare in orice limbaj. Natural, e necesar sa stim ce
lucruri trebuie evitate, dar daca nu stim cum sint ele facute
pe diferite calculatoare, aceasta inocenta ne va ajuta sa ne
protejam. (Verificatorul lui C, lint, detecteaza majoritatea de-
pendentelor de ordinea de evaluare).