Izrazi u programiranju
Izraz je u programiranju bilo koja ispravna kombinacija operanda povezanih operatorima. Različiti programski jezici posmatraju izraze na drugačiji način, a ovde ćemo vam dati neka osnovna objašnjenja.
Osnovni elementi iz kojih se sastoje izrazi su operandi i operatori. Operandi su vrednosti, dok operatori predstavljaju operacije koje se vrše.
5 + 2
U navedenom primeru, "literali" 5 i 2 predstavljaju operande, a znak operacije + je operator.
Izraz može biti sve - počev od jednog jedinog operanda, pa do bilo koje ispravne kombinacije.
x // izraz od jednog operanda
x + sin(y) - 15 // izraz sa pozivom funkcije
+ / a 9 // neispravan izraz
Operandi
Operandi su nosioci vrednosti, tačnije podaci koji učestvuju u izrazu. Operand predstavlja objekat nad kojim se vrši operacija. Umesto suvoparnih definicija, da vidimo šta može biti operand:
- literal - konstantna, bukvalna vrednost
- konstanta - veoma slično literalu, samo što se umesto bukvalne vrednosti navodi njeno ime
- promenljiva - memorijaska lokacija koja sadrži neku vrednost
Literali
Literali su neke bukvalne vrednosti. Kakve literale možemo navoditi u izrazima, zavisi od tipova podataka u programskom jeziku. Svaki tip ima svoja pravila za zapis sopstvenih vrednosti.
Celi brojevi se obično navode kao nizovi cifara. Neki programski jezici dozvoljavaju i navođenje brojeva u heksadekadnom, oktalnom ili čak binarnom sistemu. Brojevi u pokretnom zarezu (decimalni brojevi) se najčešće navode sa decimalnom tačkom (u programiranju je nebitno kako vam je podešen operativni sistem, tako da nema opasnosti da se broj nekada piše sa decimalnom tačkom, a nekad sa zarezom). U nekim jezicima je dozvoljeno i pisanje u obliku mantise i eksponenta (scientific notacija).
2326 // ovo je običan, dekadni celi broj
056 // oktalni broj (Java, JavaScript)
0x32 // heksadekadni broj (Java, JavaScript)
0b100101 // binarni broj (Java)
&56 // oktalni broj (Pascal)
$32 // heksadekadni broj (Pascal)
%100101 // binarni broj (Pascal)
123.4 // broj sa decimalama
1.234e2 // taj isti broj u "scientific" obliku
Programski jezici obično prepoznaju tip znakova (char). Ovaj tip predstavlja podatak koji se sastoji samo od jednog znaka. U starijim verzijama programskih jezika, bio je ekvivalentan jednom bajtu (ASCII standard). Moderniji programski jezici podrazumevaju da znak ima 2 ili čak 4 bajta (UNICODE standard). Stringovi (tekstualni podaci) predstavljaju nizove znakova. Danas praktično nema jezika koji nema ovaj tip podataka.
'Z' // char literal (Pascal, Java)
'Tekst' // string literal (Pascal)
"Tekst" // string literal (Java, JavaScript)
Konstante
Konstante predstavljaju nazive koji su dodeljeni određenim nepromenljivim vrednostima. Jezici imaju neke unapred definisane konstante. To može biti npr. najveći mogući celi broj koji može da se zada, ili neka poznata matematička konstanta.
MAXINT // najveći mogući celi broj (Pascal)
Math.PI // broj PI (JavaScript)
Programeri takođe mogu definisati korisničke konstante, koje koriste tokom programiranja. Ovakva programerska praksa veoma olakšava rad, pošto se umesto npr. broja koristi neki naziv. Ako se kasnije odlučimo za neku drugu vrednost, menjamo samo definiciju konstante, umesto da tražimo tu vrednost kroz ceo program. U sledećem primeru vidimo kako se definišu konstante u npr. Pascalu.
const // odeljak za definisanje konstanti
JEDAN = 1; // definicija konstante "JEDAN"
Promenljive
Promenljive predstavljaju memorijske lokacije u kojima se čuvaju vrednosti. O promenljivama smo detaljno pisali u zasebnom tekstu, pa ovde nećemo mnogo da "davimo".
Ono što je nama ovde bitno, je da promenljive sasvim ravnopravno učestvuju u izrazima. Iako na prvi pogled izgledaju isto kao korisničke konstante, razlika je suštinska - promenljive mogu menjati vrednost tokom izvršavanja programa, dok konstante to ne mogu.
Izraz koji vidimo u primeru se tumači na sledeći način: "broj 5 se sabira sa vrednošću koja se nalazi u promenljivoj x".
5 + x
Operatori
Operatori su prosto operacije koje se vrše u izrazu. Svaki programski jezik ima svoj skup operatora.
Operatori su najčešće simboli, poput +, -, *, /, &, =... Ali isto tako mogu biti i ključne reči kao div, mod, new...
Vrste operatora
Operatore najpre delimo prema tipu operacije, odnosno "šta rade" sa operandima. Tako imamo nekoliko značajnih grupa operatora...
- Aritmetički - ovo su matematičke operacije poput sabiranja, oduzimanja, množenja... Operandi su numerički i rezultat operacije bude numerička vrednost.
- Relacioni - upoređivanja vrednosti (manje, veće, jednako...). Operandi koji se upoređuju bi trebali da budu istih tipova (ili bar uporedivih), a rezultat je logičkog tipa.
- Logički - ovi operatori predstavljaju logičke operacije (AND, OR, NOT) i služe za kreiranje kompleksnijih logičkih izraza.
- Operacije nad bitovima - ove operacije (šiftovanje, rotacija, AND, OR, NOT nad bitovima) vuku poreklo iz programskih jezika nižeg nivoa, gde je manipulacija bitovima unutar bajta bila optimalan i brz način za rešavanje određenih problema.
- Postoje i drugi specifični operatori (konkatenacija stringa, operator izbora...) koji ne ulaze ni u jednu posebnu grupu.
Takođe ih možemo podeliti prema broju operanda koje povezuju, odnosno "na koje se primenjuju":
- Binarni operatori su najčešći. Oni povezuju dva operanda. Kada sabiramo dva broja - operacija sabiranja je binarna.
- Unarni operatori su nam takođe poznati. Kada menjamo znak broja (stavimo minus
ispred njega) koristimo "unarni minus". Zavisno od toga gde se ovaj operator nalazi u
odnosu na operand, mogu biti -
- prefiksni - operator ispred operanda
- postfiksni - operator iza operanda
- Ternarni operatori su već "retke zverke". Oni povezuju tri operanda. Takav je npr. operator izbora u jezicima poput JavaScripta.
Kratak pregled operatora u Viziji
Aritmetika | |||
---|---|---|---|
++ | Uvećanje | -- | Umanjenje |
+ | Sabiranje | - | Oduzimanje |
* | Množenje | / | Deljenje |
div | Celobrojno deljenje | mod, % | Ostatak celobrojnog deljenja |
Relacije | |||
< | Manje | > | Veće |
<= | Manje ili jednako | >= | Veće ili jednako |
== | Jednako | != | Različito |
=== | Strogo jednako | !== | Strogo različito |
Logika | |||
&& | Konjukcija | || | Disjunkcija |
! | Negacija | ||
Rad sa bitovima | |||
& | AND | | | OR |
^ | XOR | ~ | Negacija |
<< | Šiftovanje ulevo sa nulom | >> | Označeno šiftovanje udesno |
>>> | Šiftovanje udesno sa nulom | ||
Stringovi | |||
+ | Konkatenacija | ||
Operatori dodele | |||
= | Dodela vrednosti | %= | Dodela ostatka deljenja |
+= | Sabira i dodeljuje | -= | Oduzima i dodeljuje |
*= | Množi i dodeljuje | /= | Deli i dodeljuje |
<<= | Šiftuje i dodeljuje | >>= | Šiftuje i dodeljuje |
>>>= | Šiftuje i dodeljuje | ^= | XOR-uje i dodeljuje |
&= | AND-uje i dodeljuje | |= | OR-uje i dodeljuje |
Prioritet operatora
Kao što znamo iz matematike, neke operacije imaju prednost nad drugima. Npr. prvo se obavljaju operacije množenja i deljenja, a tek onda sabiranja i oduzimanja.
Prioritet operatora se uvek definiše u programskom jeziku, tako da se uvek tačno zna koje operacije se izvršavaju pre, a koje posle.
Naravno, ako se neki delovi izraza grupišu unutar zagrada, oni će imati veći prioritet nad ostatkom izraza. Sledeća dva izraza imaju drugačiju vrednost, upravo zahvaljujući promeni prioriteta izvršavanja operacija.
5 + x * 2
(5 + x) * 2
Ostale karakteristike operatora
Operatori mogu biti i "dvosmisleni", pošto isti simboli mogu predstavljati različite operacije. Najbolji primer je operator +, koji u većini jezika označava operaciju sabiranja, ali i konkatenaciju (dodavanje stringova). Kako će se operator tumačiti, zavisi od tipova operanda. Ovo je takozvani operatorski overloading.
5 + 2 // sabiranje brojeva
"Novi " + "Sad" // konkatenacija stringova
Neki programski jezici programeru čak dozvoljavaju i definisanje sopstvenih operatora, ali tim specijalnim mogućnostima se za sada ovde nećemo baviti.
Pozivi funkcija
U izrazima, pored operatora i operanda, mogu učestvovati i pozivi funkcija, koji se onda sa ostalim operandima povezuju operatorima.
Ako poziv funkcije posmatrate kao operand, nećete pogrešiti. Pošto funkcija (uobičajeno) vraća vrednost, ona je takođe nosilac vrednosti, kao literal ili promenljiva.
Ako već hoćemo da idemo "u sitna crevca", posebno ako posmatramo neke modernije programske jezike, mogli bismo reći da je naziv funkcije operand, dok su zagrade koje se navode posle naziva operator poziva funkcije.
Ovo ima smisla u jezicima poput JavaScripta gde je funkcija istovremeno i objekat, pa tako njen naziv predstavlja referencu.
Ono što je nama bitno je da funkcija u izrazu treba da vrati neku vrednost, koja se onda koristi u izrazu. Funkcija može imati jedan ili više parametara (odvojenih zarezom), a svaki parametar (što u stvari zavisi od izvođenja funkcije) treba da ima vrednost, odnosno može ponovo predstavljati čitav izraz.
5 + sqrt(x+3) * y // poziv funkcije u izrazu
Vrednost izraza
U "striktnim" programskim jezicima kao što je Pascal, izraz mora imati vrednost. Samim tim, i svi operandi takođe moraju imati vrednost. U Pascalu izraz ne sme stajati nezavisno, već mora biti "upotrebljen".
y := x + 5; // naredba dodele - vrednost izraza se dodeljuje promenljivoj y
U jezicima poput JavaScripta, izrazi mogu stajati i nezavisno, kao naredbe. Takođe mogu, ali i ne moraju imati vrednost. Ako se ne koristi, vrednost izraza, se prosto gubi.
5; // i ovo je izraz i može biti samostalan
y = x + 5; // ono što je u Pascalu naredba, u JavaScriptu je operacija
poziv(a, b); // poziv funkcije takođe može biti samostalan
Implicitna konverzija tipova
Ne zaboravite da programski jezici mogu vršiti određene konverzije tipova u izrazima, i bez intervencije programera. Najčešća konverzija, (o kojoj često ni ne razmišljamo) je kada u izrazu učestvuju celi brojevi i brojevi u pokretnom zarezu. Tada se vrednosti operanda konvertuju u "širi" tip, odnosno u decimalne brojeve.
Naravno, različiti jezici imaju različita pravila za konverziju. Na primer Pascal neće dozvoliti kombinaciju broja i stringa bez eksplicitne konverzije broja-u-tekst ili teksta-u-broj. Sa druge strane, JavaScript i PHP neće imati takvih problema.
'Vrednost je ' + 5; // zabraneno u Pascalu, ali dozvoljeno u JavaScriptu
Nus-efekti izraza
Izrazi mogu imati i nus-pojave (side effects). Osim što se njihova vrednost "koristi", može se desiti da ostave još neke posledice na vrednostima promenljivih ili da čak utiču i na samo izvršavanje programa. Postoje dve tipične situacije u kojima se ovi efekti ispoljavaju:
- operatori menjaju vrednost operanda - operatori uvećanja (++) i umanjenja (--) koji postoje u jezicima koji potiču iz jezika C, primenjuju se na numeričke promenljive i menjaju i njihovu vrednost
- izvršavanje korisničkih funkcija - veoma čest slučaj "uzgrednog efekta" - funkcija može obaviti veliki broj zadataka koji nemaju mnogo veze sa njenom povratnom vrednošću, može menjati vrednost globalnih promenljivih u programu ili čak i samih parametara
U JavaScriptu ne postoje "procedure" kao poseban tip potprograma koji postoji u Pascalu. Sve se obavlja pomoću funkcija. Funkcije ne moraju vraćati vrednost i kada ih pozivamo, praktično kreiramo izraz koji je značajan samo zbog svojih "uzgrednih" efekata.
- Expression
- Expression (computer science)
- T. Valentine, J. Reid (2013): JavaScript Programmers Reference, Apress, New York