Noi te platim pentru timpul acordat , o postare , like , vizualizare subiect , sau creare subiect , insemna castig.
Suntem comunitatea unica din Romania care plateste pentru efortul depus . Ideile ,opiniile tale conteaza si sunt platite doar la noi.

Operatori şi expresii

Operatori şi expresii

Solus

Membru
Staff member
Fondator BitArena
Moderator
Utilizator
Joined
Jul 6, 2018
Messages
523
Reaction score
94
Points
26
Location
Bucuresti
Website
www.bitarena.eu

Reputation:

Limbajul C prezintă un număr mare de operatori, caracterizaţi prin diferite nivele de prioritate sau precedenţă.
În acest capitol descriem operatorii în ordinea descrescătoare a precedenţei lor. Operatorii descrişi în acelaşi paragraf au aceeaşi precedenţă. Vom specifica de fiecare dată dacă asociativitatea este la stînga sau la dreapta.
Expresiile combină variabile şi constante pentru a produce valori noi şi le vom introduce pe măsură ce vom prezenţa operatorii.

Expresii primare

Expresie-primară:
identificator
constantă
şir
(expresie)
expresie-primară [expresie]
expresie-primară (listă-expresii<opt>)
valoare-stînga . identificator
expresie-primară -> identificator
Listă-expresii:
expresie
listă-expresii, expresie

Un identificator este o expresie-primară, cu condiţia că el să fi fost declarat corespunzător. Tipul său este specificat în declaraţia sa.
Dacă tipul unui identificator este „masiv de ...”, atunci valoarea expresiei-identificator este un pointer la primul obiect al masivului, iar tipul expresiei este „pointer la ...”. Mai mult, un identificator de masiv nu este o expresie valoare-stînga.
La fel, un identificator declarat de tip „funcţie care returnează ...”, care nu apare pe poziţie de apel de funcţie este convertit la „pointer la funcţie care returnează ...”.
O constantă este o expresie-primară. Tipul său poate fi int, long sau double. Constantele caracter sînt de tip int, constantele flotante sînt de tip long double.
Un şir este o expresie-primară. Tipul său original este „masiv de caractere”, dar urmînd aceleaşi reguli descrise mai sus pentru identificatori, acesta este modificat în „pointer la caracter” şi rezultatul este un pointer la primul caracter al şirului. Există cîteva excepţii în anumite iniţializări (vezi paragraful 5.4).
O expresie între paranteze rotunde este o expresie-primară, al cărei tip şi valoare sînt identice cu cele ale expresiei din interiorul parantezelor (expresia din paranteze poate fi şi o valoare-stînga).
O expresie-primară urmată de o expresie între paranteze pătrate este o expresie-primară. Sensul intuitiv este de indexare. De obicei expresia-primară are tipul „pointer la ...”, expresia-indice are tipul int, iar rezultatul are tipul „...”. O expresie de forma E1[E2] este identică (prin definiţie) cu *((E1)+(E2)), unde * este operatorul de indirectare.
Un apel de funcţie este o expresie-primară. Ea constă dintr-o expresie-primară urmată de o pereche de paranteze rotunde, care conţin o listă-expresii separate prin virgule. Lista-expresii constituie argumentele reale ale funcţiei; această listă poate fi şi vidă. Expresia-primară trebuie să fie de tipul „funcţie care returnează ...”, iar rezultatul apelului de funcţie va fi de tipul „...”.
Înaintea apelului, oricare argument de tip float este convertit la tipul double, oricare argument de tip char sau short este convertit la tipul int. Numele de masive sînt convertite în pointeri la începutul masivului. Nici o altă conversie nu se efectuează automat.
Dacă este necesar pentru ca tipul unui argument actual să coincidă cu cel al argumentului formal, se va folosi un cast (vezi secţiunea 3.4).
Sînt permise apeluri recursive la orice funcţie.
O valoare-stînga urmată de un punct şi un identificator este o expresie-primară. Valoarea-stînga denumeşte o structură sau o reuniune (vezi capitolul 10) iar identificatorul denumeşte un membru din structură sau reuniune. Rezultatul este o valoare-stînga care se referă la membrul denumit din structură sau reuniune.
O expresie-primară urmată de o săgeată (constituită dintr-o liniuţă şi semnul > urmată de un identificator este o expresie-primară. Prima expresie trebuie să fie un pointer la o structură sau reuniune, iar identificatorul trebuie să fie numele unui membru din structura sau reuniunea respectivă. Rezultatul este o valoare-stînga care se referă la membrul denumit din structura sau reuniunea către care indică expresia pointer.
Expresia E1->E2 este identică din punctul de vedere al rezultatului cu (*E1). E2
Descriem în continuare operatorii limbajului C împreună cu expresiile care se pot constitui cu aceşti operatori.

Operatori unari

Toţi operatorii unari au aceeaşi precedenţă, iar expresiile unare se grupează de la dreapta la stînga.

Expresie-unară:
* expresie
& valoare-stînga
- expresie
! expresie
~ expresie
++ valoare-stînga
-- valoare-stînga
valoare-stînga ++
valoare-stînga --
(nume-tip) expresie
sizeof (nume-tip)

Operatorul unar * este operatorul de indirectare. Expresia care-l urmează trebuie să fie un pointer, iar rezultatul este o valoare-stînga care se referă la obiectul către care indică expresia. Dacă tipul expresiei este „pointer la ...” atunci tipul rezultatului este „...”. Acest operator tratează operandul său ca o adresă, face acces la ea şi îi obţine conţinutul.
Exemplu: instrucţiunea y = *px; atribuie lui y conţinutul adresei către care indică px.

Operatorul unar & este operatorul de obţinere a adresei unui obiect sau de obţinere a unui pointer la obiectul respectiv. Operandul este o valoare-stînga iar rezultatul este un pointer la obiectul referit de valoarea-stînga. Dacă tipul valorii-stînga este „...” atunci tipul rezultatului este „pointer la ...”.
Exemplu. Fie x o variabilă de tip int şi px un pointer creat într-un anumit fel (vezi capitolul 9). Atunci prin instrucţiunea
px = &x;
se atribuie variabilei de tip „pointer la int” px adresa variabilei x; putem spune acum că px indică spre x. Secvenţa:
px = &x; y = *px;
este echivalentă cu
y = x;

Operatorul & poate fi aplicat numai la variabile şi la elemente de masiv. Construcţii de forma &(x+1) şi &3 nu sînt admise. De asemenea nu se admite ca variabila să fie de clasă register.
Operatorul unar & ajută la transmiterea argumentelor de tip adresă în funcţii.
Operatorul unar - este operatorul de negativare. Operandul său este o expresie, iar rezultatul este negativarea operandului. În acest caz sînt aplicate conversiile aritmetice obişnuite. Negativarea unui întreg de tip unsigned se face scăzînd valoarea sa din 2n, unde n este numărul de biţi rezervaţi tipului int.
Operatorul unar ! este operatorul de negare logică. Operandul său este o expresie, iar rezultatul său este 1 sau 0 după cum valoarea operandului este 0 sau diferită de zero. Tipul rezultatului este int. Acest operator este aplicabil la orice expresie de tip aritmetic sau la pointeri.
Operatorul unar ~ (tilda) este operatorul de complementare la unu. El converteşte fiecare bit 1 la 0 şi invers. El este un operator logic pe biţi.
Operandul său trebuie să fie de tip întreg. Se aplică conversiile aritmetice obişnuite.
Operatorul unar ++ este operatorul de incrementare. Operandul său este o valoare-stînga. Operatorul produce incrementarea operandului cu 1. Acest operator prezintă un aspect deosebit deoarece el poate fi folosit ca un operator prefix (înaintea variabilei: ++n) sau ca un operator postfix (după variabilă: n++). În ambele cazuri efectul este incrementarea lui n. Dar expresia ++n incrementează pe n înainte de folosirea valorii sale, în timp ce n++ incrementează pe n după ce valoarea sa a fost utilizată. Aceasta înseamnă că în contextul în care se urmăreşte numai incrementarea lui n, oricare construcţie poate fi folosită, dar într-un context în care şi valoarea lui n este folosită ++n şi n++ furnizează două valori distincte.

Exemplu: dacă n este 5, atunci
x = n++ ; atribuie lui x valoarea 5
x = ++n ; atribuie lui x valoarea 6
În ambele cazuri n devine 6.

Rezultatul operaţiei nu este o valoare-stînga, dar tipul său este tipul valorii-stînga.
Operatorul unar -- este operatorul de decrementare. Acest operator este analog cu operatorul ++ doar că produce decrementarea cu 1 a operandului.
Operatorul (nume-tip) este operatorul de conversie de tip. Prin nume-tip înţelegem unul dintre tipurile fundamentale admise în C. Operandul acestui operator este o expresie. Operatorul produce conversia valorii expresiei la tipul denumit. Această construcţie se numeşte cast.
Operatorul sizeof furnizează dimensiunea în octeţi a operandului său. Aplicat unui masiv sau structuri, rezultatul este numărul total de octeţi din masiv sau structură. Dimensiunea se determină în momentul compilării, din declaraţiile obiectelor din expresie. Semantic, această expresie este o constantă întreagă care se poate folosi în orice loc în care se cere o constantă. Cea mai frecventă utilizare o are în comunicarea cu rutinele de alocare a memoriei sau rutinele I/O sistem.
Operatorul sizeof poate fi aplicat şi unui nume-tip între paranteze. În acest caz el furnizează dimensiunea în octeţi a unui obiect de tipul indicat.
Construcţia sizeof(nume-tip) este luată ca o unitate, astfel că expresia
sizeof(nume-tip)-2
este acelaşi lucru cu
(sizeof(nume-tip))-2

Operatori multiplicativi
Operatorii multiplicativi * / şi % sînt operatori aritmetici binari şi se grupează de la stînga la dreapta.

Expresie-multiplicativă:
expresie * expresie
expresie / expresie
expresie % expresie

Operatorul binar * indică înmulţirea. Operatorul este asociativ, dar în expresiile în care apar mai mulţi operatori de înmulţire, ordinea de evaluare nu se specifică. Compilatorul rearanjează chiar şi un calcul cu paranteze. Astfel a*(b*c) poate fi evaluat ca (a*b)*c. Aceasta nu implică diferenţe, dar dacă totuşi se doreşte o anumită ordine, atunci se vor introduce variabile temporare.
Operatorul binar / indică împărţirea. Cînd se împart două numere întregi pozitive, trunchierea se face spre zero; dacă unul dintre operanzi este negativ atunci trunchierea depinde de sistemul de calcul.
Operatorul binar % furnizează restul împărţirii primei expresii la cea de a doua. Operanzii nu pot fi de tip float. Restul are totdeauna semnul deîmpărţitului. Totdeauna (a/b)*b+a%b este egal cu a (dacă b este diferit de 0). Sînt executate conversiile aritmetice obişnuite.

Operatori aditivi

Operatorii aditivi + şi - sînt operatori aritmetici binari şi se grupează de la stînga la dreapta. Se execută conversiile aritmetice obişnuite,

Expresie-aditivă:
expresie + expresie
expresie - expresie

Operatorul binar + produce suma operanzilor săi. El este asociativ şi expresiile care conţin mai mulţi operatori pot fi rearanjate la fel ca în cazul operatorului de înmulţire.
Operatorul binar - produce diferenţa operanzilor săi

Operatori de deplasare

Operatorii de deplasare << şi >> sînt operatori logici pe biţi. Ei se grupează de la stînga la dreapta.

Expresie-deplasare:
expresie << expresie
expresie >> expresie

Operatorul << produce deplasarea la stînga a operandului din stînga cu un număr de poziţii binare dat de operandul din dreapta.
Operatorul >> produce deplasarea la dreapta a operandului din stînga cu un număr de poziţii binare dat de operandul din dreapta.
În ambele cazuri se execută conversiile aritmetice obişnuite asupra operanzilor, fiecare dintre ei trebuind să fie de tip întreg. Operandul din dreapta este convertit la int; tipul rezultatului este cel al operandului din stînga. Rezultatul este nedefinit dacă operandul din dreapta este negativ sau mai mare sau egal cu lungimea obiectului, în biţi. Astfel valoarea expresiei E1<<E2 este E1 (interpretată ca şi configuraţie de biţi) deplasată la stînga cu E2 poziţii bit; biţii eliberaţi devin zero. Expresia E1>>E2 este E1 deplasată la dreapta cu E2 poziţii binare. Deplasarea la dreapta este logică (biţii eliberaţi devin 0) dacă E1 este de tip unsigned; altfel ea este aritmetică (biţii eliberaţi devin copii ale bitului semn).

Exemplu: x<<2 deplasează pe x la stînga cu 2 poziţii, biţii eliberaţi devin 0; aceasta este echivalent cu multiplicarea lui x cu 4.

Operatori relaţionali

Operatorii relaţionali <, >, <=, >= se grupează de la stînga la dreapta.

Expresie-relaţională:
expresie < expresie
expresie > expresie
expresie <= expresie
expresie >= expresie

Operatorii < (mai mic), > (mai mare), <= (mai mic sau egal) şi >= (mai mare sau egal) produc valoarea 0 dacă relaţia specificată este falsă şi 1 dacă ea este adevărată.
Tipul rezultatului este int. Se execută conversiile aritmetice obişnuite. Aceşti operatori au precedenţa mai mică decît operatorii aritmetici, astfel că expresia i<x-1 se consideră i<(x-1) aşa după cum ne aşteptam.

Operatori de egalitate

Expresie-egalitate:
expresie == expresie
expresie != expresie

Operatorii == (egal cu) şi != (diferit de) sînt analogi cu operatorii relaţionali, dar precedenţa lor este mai mică. Astfel a<b == c<d este 1, dacă a<b şi c<d au aceeaşi valoare de adevăr.

Operatorul ŞI pe biţi

Expresie-ŞI:
expresie & expresie

Operatorul & este operatorul „ŞI” logic pe biţi. El este asociativ şi expresiile care conţin operatorul & pot fi rearanjate. Rezultatul este funcţia logică „ŞI” pe biţi aplicată operanzilor săi. Operatorul se aplică numai la operanzi de tipuri întregi. Legea după care funcţionează este:

You must be registered for see images attach


Operatorul & este deseori folosit pentru a masca o anumită mulţime de biţi: de exemplu:
c = n & 0177;
pune pe zero toţi biţii afară de ultimii 7 biţi de ordin inferior ai lui n, fără a afecta conţinutul lui n.

Operatorul SAU-exclusiv pe biţi

Expresie-SAU-exclusiv:
expresie ^ expresie

Operatorul ^ este operatorul „SAU-exclusiv” logic pe biţi. El este asociativ şi expresiile care-l conţin pot fi rearanjate. Rezultatul este funcţia logică „SAU-exclusiv” pe biţi aplicată operanzilor săi. Operatorul se aplică numai la operanzi de tipuri întregi. Legea după care funcţionează este:
You must be registered for see images attach

Operatorul | este folosit pentru a poziţiona biţi; de exemplu:
x = x | MASK;
pune pe 1 toţi biţii din x care corespund la biţi poziţionaţi pe 1 din MASK. Se efectuează conversiile aritmetice obişnuite.

Operatorul ŞI-logic

Expresie-ŞI-logic:
expresie && expresie

Operatorul && este operatorul „ŞI-logic” şi el se grupează de la stînga la dreapta. Rezultatul este 1 dacă ambii operanzi sînt diferiţi de zero şi 0 în rest. Spre deosebire de operatorul ŞI pe biţi &, operatorul ŞI-logic && garantează o evaluare de la stînga la dreapta; mai mult, al doilea operand nu este evaluat dacă primul operand este 0.
Operanzii nu trebuie să aibă în mod obligatoriu acelaşi tip, dar fiecare trebuie să aibă unul dintre tipurile fundamentale sau pointer. Rezultatul este totdeauna de tip int.

Operatorul SAU-logic

Expresie-SAU-logic:
expresie || expresie

Operatorul || este operatorul „SAU-logic” şi el se grupează de la stînga la dreapta. Rezultatul este 1 dacă cel puţin unul dintre operanzi este diferit de zero şi 0 în rest.
Spre deosebire de operatorul SAU-inclusiv pe biţi |, operatorul SAU-logic || garantează o evaluare de la stînga la dreapta; mai mult, al doilea operand nu este evaluat dacă valoarea primului operand este diferită de zero.
Operanzii nu trebuie să aibă în mod obligatoriu acelaşi tip, dar fiecare trebuie să aibă unul dintre tipurile fundamentale sau pointer. Rezultatul este totdeauna de tip int.

Operatorul condiţional

Expresie-condiţională:
expresie ? expresie : expresie

Operatorul condiţional ? este un operator ternar. Prima expresie se evaluează şi dacă ea este diferită de zero sau adevărată, rezultatul este valoarea celei de-a doua expresii, altfel rezultatul este valoarea expresiei a treia. De exemplu expresia:
z = (a>b) ? a : b;
calculează maximul dintre a şi b şi îl atribuie lui z. Se evaluează mai întîi prima expresie a>b. Dacă ea este adevărată se evaluează a doua expresie şi valoarea ei este rezultatul operaţiei, această valoare se atribuie lui z. Dacă prima expresie nu este adevărată atunci z ia valoarea lui b.
Expresia condiţională poate fi folosită peste tot unde sintaxa cere o expresie.
Dacă este posibil, se execută conversiile aritmetice obişnuite pentru a aduce expresia a doua şi a treia la un tip comun; dacă ambele expresii sînt pointeri de acelaşi tip, rezultatul are şi el acelaşi tip; dacă numai o expresie este un pointer, cealaltă trebuie sa fie constanta 0, iar rezultatul este de tipul pointerului. Întotdeauna numai una dintre expresiile a doua şi a treia este evaluată.
Dacă f este flotant şi n întreg, atunci expresia
(h>0)? f : n
este de tip double indiferent dacă n este pozitiv sau negativ. Parantezele nu sînt necesare deoarece precedenţa operatorului ?:este mai mică, dar ele pot fi folosite pentru a face expresia condiţională mai vizibilă.

Operatori de atribuire

Există mai mulţi operatori de atribuire, care se grupează toţi de la dreapta la stînga. Operandul stîng este o valoare-stînga, operandul drept este o expresie. Tipul expresiei de atribuire este tipul operandului stîng.
Rezultatul este valoarea memorată în operandul stîng după ce atribuirea a avut loc. Cele două părţi ale unui operator de atribuire compus sînt unităţi lexicale (simboluri) distincte.

Expresie-atribuire:
valoare-stînga = expresie
valoare-stînga op= expresie
unde op poate fi unul din operatorii +, -, *, /, %, <<, >>, &, ^, |.

Într-o atribuire simplă cu =, valoarea expresiei înlocuieşte pe cea a obiectului referit de valoare-stînga. Dacă ambii operanzi au tip aritmetic, atunci operandul drept este convertit la tipul operandului stîng înainte de atribuire.
Expresiile de forma E1 op= E2 se interpretează ca fiind echivalente cu expresiile de forma E1 = E1 op E2; totuşi E1 este evaluată o singură dată.

Exemplu: expresia x *= y+1 este echivalentă cu
x = x * (y+1) şi nu cu x = x * y + 1

Pentru operatorii += şi -=, operandul stîng poate fi şi un pointer, în care caz operandul din dreapta este convertit la întreg (vezi capitolul 9). Toţi operanzii din dreapta şi toţi operanzii din stînga care nu sînt pointeri trebuie să fie de tip aritmetic.
Atribuirea prescurtată este avantajoasă în cazul cînd în membrul stîng avem expresii complicate, deoarece ele se evaluează o singură dată.

Operatorul virgulă

Expresie-virgulă:
expresie , expresie

O pereche de expresii separate prin virgulă se evaluează de la stînga la dreapta şi valoarea expresiei din stînga se neglijează. Tipul şi valoarea rezultatului sînt cele ale operandului din dreapta. Aceşti operatori se grupează de la stînga la dreapta. În contextele în care virgula are un sens special, (de exemplu într-o listă de argumente reale ale unei funcţii şi lista de iniţializare), operatorul virgulă descris aici poate apărea numai în paranteze. De exemplu funcţia:
f(a,(t=3,t+2),c)
are trei argumente, dintre care al doilea are valoarea 5. Expresia acestui argument este o expresie virgulă. În calculul valorii lui se evaluează întîi expresia din stînga şi se obţine valoarea 3 pentru t, apoi cu această valoare se evaluează a doua expresie şi se obţine t=5. Prima valoare a lui t se pierde.

Precedenţa şi ordinea de evaluare

Tabelul de la sfîrşitul acestei secţiuni constituie un rezumat al regulilor de precedenţă şi asociativitate ale tuturor operatorilor.
Operatorii din aceeaşi linie au aceeaşi precedenţă; liniile sînt scrise în ordinea descrescătoare a precedenţei, astfel de exemplu operatorii *, / şi % au toţi aceeaşi precedenţă, care este mai mare decît aceea a operatorilor + şi -.
După cum s-a menţionat deja, expresiile care conţin unul dintre operatorii asociativi sau comutativi (*, +, &, ^, |) pot fi rearanjate de compilator chiar dacă conţin paranteze. În cele mai multe cazuri aceasta nu produce nici o diferenţă; în cazurile în care o asemenea diferenţă ar putea apărea pot fi utilizate variabile temporare explicite, pentru a forţa ordinea de evaluare.
Limbajul C, ca şi multe alte limbaje, nu specifică în ce ordine sînt evaluaţi operanzii unui operator. De exemplu într-o instrucţiune de forma:
x = f() + g();
f poate fi evaluată înainte sau după evaluarea lui g; dacă f sau g alterează o variabilă externă de care cealaltă depinde, xpoate depinde de ordinea de evaluare. Din nou rezultate intermediare trebuie memorate în variabile temporare pentru a asigura o secvenţă particulară.

You must be registered for see images attach
 
Top