Operatori, izrazi, naredbe, gubitak preciznosti
(sve isto važi i za C i za C++)
Operatori:
Verovatno vam je poznat termin „operator“, dakle to je npr. +, -, / itd...
Jezik C (i C++) ima ogroman skup operatora.
Postoji par bitnih stvari: prvenstvo operatora, asocijativnost, značenje itd...
Izrazi i naredbe
Primer - sabiranje dva broja : a + b. Rezultat smeštamo u promenljivu rez, ako od ovih podataka formiramo izraz u jeziku C (i C++) dobijamo ovo:
rez = a + b;
Izraz je kombinacija operanada i operatora. U navedenom primeru imamo 3 operanda (rez, a, b) i dva operatora ( =, +). Takođe postoje i dva izraza, prvi je sabiranje promenljive a i b, drugi je dodeljivanje te vrednosti promenljivoj rez. Sve ovo zajedno čini jednu naredbu.
Naredba je skup izraza čiji broj može biti neograničeno veliki, ali takođe može biti i 0 (prazna naredba) koji se obavezno okončava znakom „tačka-zarez“( ; ).
Operatori u jeziku C (i C++)
Važan faktor je svakako prvenstvo operatora, što znači da ako napišete naredbu :
rez = a - b * 2
prvo će se izvršiti izraz b * 2 pa će se od a oduzeti rezultat množenja i na kraju se ta razlika dodeljuje promenljivoj rez. Operator množenja ima najveće prvenstvo, zatim operator oduzimanja i da najmanje prvenstvo ima operator dodele vrednosti.
Ako u navedenom izrazu želite da prvo odradite sabiranje morate upotrebiti zagrade:
rez = (a + b) * 2;
Ili možete da napišete u više naredbi:
rez = a + b;
rez = rez * 2;
ovo je prosto i jasno. Međutim postoji „skraćenica“ koju možemo primeniti na izraz rez = rez * 2, umesto da dva puta pišemo „rez“ napisaćemo izraz:
rez *= 2;
što će imati isti efekat.
Možda niste upoznati sa značenjem operatora ostatka(moduo) - %. Ukoliko bi imali izraz:
rez = 10 / 2;
rezultat bi bio 5 i taj broj bi se dodelio promenljivoj rez. Ostatka pri deljenju 10 sa 2 nema pa je on nula. No, ako želimo da rez sadrži ostatak od 10 / 2 koristićemo operator moduo:
rez = 10 % 2;
rez će imati vrednost 0.
Gubitak preciznosti
Ranije smo rekli koji tipovi promenljivih mogu čuvati koje podatke. Ako imamo promenljivu X tipa int i promenljivu Y tipa float te napišemo sledeće:
int X;
float Y = 3.14;
X = Y;
vrednost koju čuva X neće biti 3.14 jer je X tipa int a taj tip ne može da čuva brojeve sa decimalnom tačkom (realne brojeve). X će imati vrednost 3, dakle deo posle decimalne tačke se odbacuje i dolazi do gubitka preciznosti.
Postoji veoma bitna stvar koja može biti vrlo nezgodna. Pogledajmo primer:;
float Y;
Y = 10 / 4;
očekivano je vrednost Y 2.5 ali nije! Vrednost Y je u stvari 2! Zašto? Analizirajmo naredbu Y=10/4. Prvo se obavlja deljenje pa tek onda dodeljivanje vrednosti. Kada se deljenje obavlja sistemu je potrebna memorija u koju će privremeno smestiti vrednost deljenja pre nego što tu vrednosti dodeli promenljivoj Y, dakle sistem će kreirati privremenu promenljivu. Treba se zapitati kojeg je tipa ta promenljiva. Radi optimizacije iskorišćenja memorije, sistem će kreirati promenljivu onog tipa u koji će moći da stane rezultat deljenja (sabiranja, množenja...) drugim rečima ako su oba operanda tipa int (što je ovde slučaj) sistem pravi promenljivu tipa int i dodeljuje joj odgovarajuću vrednost, a pošto int ne može čuvati brojeve iza decimalnog zareza (bez obzira što je Y tipa float jer se njemu vrednost tek kasnije dodeljuje) dolazi do gubitka preciznosti.
Dva su načina za izbegavanje ovakvog ponašanja. Prvi, možemo uraditi ovo:
Y = 10 / 4 * 1.0;
dodali smo „ * 1.0 “ izrazu i time smo postigli da postoje dve promenljive tipa int (10, 4) i jedna tipa float( 1.0 ). Pomoćna promenljiva koju je za sebe kreirao sistem će samim tim biti tipa float pa neće biti gubitka preciznosti. Sve pomoćne promenljive sistem automatski briše po završetku naredbe i tako vraća zauzetu memoriju.
Drugi način je elegantniji, koristićemo operator eksplicitne konverzije (gore pomenuta je bila inplicitna) takođe zvanog „cast operator“. Koristeći ovaj način dobićemo naredbu:
Y = (float) 10 / 4;
Uz pomoć (float) smo promenili tip broja 10 iz int u float. Unutar zagrada možete stavljati različite tipove i na taj način dolaziti do različitih konverzija.
Operatori inkrementiranja(++) i dekrementiranja(--)
Imamo promenljivu X kojoj smo dodelili vrednost 15.
int X = 15;
Želimo da joj povećamo vrednost za 1 (možda deluje sumanuto ali veoma često ćete se sretati sa ovakvom potrebom). To možemo uraditi na nekoliko načina:
X = X + 1;
X +=1;
X++;
Prva dva izraza su vam poznata ali treći izraz je novi, to je takozvana inkrementacija. Ona znači da će se vrednosti promenljive X povećati za 1, da stoji X-- vrednost bi se smanjila za 1. Uvedena je jer je mnogo lakše/brže napisati X++ nego X = X + 1, zar ne? Međutim operator ++ može stojati i kako pre tako i posle imena promenljive, ovako:
Y = 10 + X++;
Y = 10 + ++X;
Razlika nije zanemarljiva. Uzmimo da je X = 15. U prvom slučaju vrednost Y će biti 10 + 15. U drugom Y će biti 10 + 16. Razlika je u tome što se u prvom slučaju vrednost X inkrementira tek po završetku naredbe (takozvana „postfiksna notacija“) dok se vrednost X u drugom slučaju prvo izvršava inkrementacija promenljive X pa se tek onda odrađuje sabiranje, pa u tom trenutku promenljiva X ima vrednost 16. Ovo se naziva „prefiksna notacija“.
Napomena:
Kod pisanja realnih brojeva npr. 3.14 od esencijalne je važnosti da greškom ne upotrebite operator zareza( , ) umesto operatora tačka( . ). U sintaksi jezika C (i C++) ovi operatori imaju potpuno različito znacenje!
Operatori poređenja u jeziku C
Kako funkcionisu operatori poređenja? Ako želite da proverite da li je 1 veće od 2 izraz bi izgledao ovako : X = 1 > 2 . Ovo nije tačno pa je rezultat koji će biti smešten u promenljivu X jednak nuli. Međutim da smo napisali X = 5 > 2 , uslov bi bio tačan i vrednost u promenljivoj X bi bila jedan. Dakle ako je iskaz poređenja tačan dobija se broj jedan, ako je rezultat poređenja netačan dobija se broj nula.
Sa nulom predstavlja neispunjavanje nekog uslova a sa jednicom(ili bilo kojim brojem koji je različit od nule) tačnost.
Prema tome sve petlje i naredbe grananja će se izvršavati kada god je rezultat uslova koji smo zadali različit od nule. Evo liste operatora poređenja :
-------------------------------------------------
OPERATOR | Znacenje |
-------------------------------------------------
< Manje od
<= Manje ili jednako
> Vece od
>= Vece ili jednako
!= Različito
== Jednakost
---------------------------------------------
Treba zapaziti razliku između operatora dodele vrednost = i operatora jednakosti ==. Ako imamo ovakvu situaciju :
int X, Y, Z;
X = 10;
Y = 23;
Z = (Y == X);
Vrednost u Z će biti 0, jer Y nije jednako X pa uslov nije ispunjen. Ako bi umesto poslednje naredbe stojala ova:
Z = ( Y != X );
vrednost u Z će biti 1 jer je Y zaista različito od X pa je samim tim uslov zadovoljen. Ovde su zagrade napisane zbog bolje preglednosti inače prvenstvo operatora != je veće od operatora jednako( = ) pa i nema potrebe za zagradama ali dakle ne škodi staviti ih.