Slijedna točka

Izvor: Hrvatska internetska enciklopedija
Skoči na:orijentacija, traži

Slijedna točka u imperativnom programiranju definira bilo koju točku u izvršavanju računalnog programa na kojoj je zajamčeno da su na djelu svi nusefekti prijašnjih evaluacija i da nisu na djelu nusefekti budućih evaluacija. Često su spominjane vezano uz C ili C++, jer rezultat nekih izraza može ovisiti o redoslijedu evaluacije njihovih podizraza. Dodavanje jedne ili više slijednih točaka metoda je osiguravanja konzistentnih rezultata, jer se time ograničavaju mogući redoslijedi evaluacije.

Primjeri dvosmislenosti

Pogledajmo dvije funkcije f() i g(). U programskim jezicima C i C++ + operator nije slijedna točka, i prema tome je u izrazu f()+g() moguće da će najprije biti izvršen ili f() ili g(). Zarez operator je slijedna točka, pa je stoga u kodu f(),g() redoslijed evaluacije definiran (tj. najprije je pozvan f(), a zatim je pozvan f()). Tip i vrijednost cijelog izraza je vrijednost od g(); vrijednost od f() se odbacuje.

Slijedne točke treba razmatrati i kada je ista varijabla modificirana više od jednom unutar istog izraza. Često citiran primjer je izraz i=i++, koji ujedno i pridružuje i samome sebi i inkrementira i. Konačna vrijednost od i je upitna, jer, ovisno o semantici jezika, inkrement se može pojaviti prije, poslije ili paralelno s pridruživanjem. Definicija pojedinog jezika može specificirati jednog od mogućih ponašanja, ili jednostavno opisati ovo ponašanje kao nedefinirano. U programskim jezicima C i C++ evaluacija takvog izraza daje nedefinirano ponašanje.

Slijedne točke u programskim jezicima C i C++

U programskim jezicima C[1] i C++[2], slijedne točke se pojavljuju na sljedećim mjestima. (U C++u, preopterećenje operatora se ponaša kao funkcija, pa prema tome operatori, koji su preopterećeni, uvode slijedne točke jednako kao što to čine regularni pozivi funkcije.)

  1. Između evaluacije lijevog i desnog operanda operatora && (logičko I), operatora || (logičko ILI) i operatora zarez. Na primjer, u izrazu *p++ != 0 && *q++ != 0, sve posljedice podizraza *p++ != 0 su završene prije bilo kakvog pokušaja pristupanja varijabli q.
  2. Između evaluacije prvog operanda ternarnog operatora ("upitnik") i drugog ili trećeg operanda. Na primjer, u izrazu a = (*p++) ? (*p++) : 0 postoji slijedna točka nakon prvog podizraza *p++, što znači da je već inkrementiran do izvršavanja drugog podizraza.
  3. Na kraju punog izraza. Ova kategorija uključuje naredbe s izrazima (kao što je pridruživanje a=b;), return naredba, kontrolni izrazi if, switch, while, ili do-while naredbe, i sva tri izraza u for naredbi.
  4. Prije ulaska u funkciju u pozivu funkcije. Redoslijed kojim su argumenti evaluirani nije specificiran, ali ova slijedna točka znači da su svi nusefekti završeni prije ulaska u funkciju. U izrazu f(i++) + g(j++) + h(k++), f je pozvan s parametrom originalne vrijednosti varijable i, ali i je inkrementiran prije ulaska u tijelo funkcije f. Slično tome, j i k su ažurirani prije ulaska u g i h. Međutim, nije specificirano kojim redoslijedom se izvršavaju f(), g() i h(), niti kojim redoslijedom su i, j i k inkrementirani. Vrijednosti varijabli j i k u tijelu funkcije f su prema tome nedefinirane. [3] Primijetite da poziv f(a,b,c) ne predstavlja uporabu zarez operatora i da redoslijed evaluacije za a, b, and c nije specificiran.
  5. Na povratku iz funkcije, nakon što je povratna vrijednost kopirana u kontekst poziva. (Ova slijedna točka je specificirana samo u C++ standardu; prisutna je samo implicitno u C-u[4].)
  6. Na kraju inicijalizatora; na primjer, nakon evaluacije od 5 u deklaraciji int a = 5;.

Reference

  1. Dodatak C C99 specifikacije navodi okolnosti po kojima se slijedne točke mogu podrazumijevati.
  2. C++ standard iz 1998. navodi slijedne točke za taj jezik u odjeljku 1.9, paragraf 16–18.
  3. Klauzula 6.5#2 C99 specifikacije: "Između prethodne i sljedeće slijedne točke objektu će vrijednost koju sprema biti promijenjena najviše jednom u evaluaciji izraza. Nadalje, prijašnjoj vrijednosti će se pristupiti isključivo radi određivanja vrijednosti koja treba biti spremljena." Pristupanjem vrijednosti od j unutar f dakle invocira nedefinirano ponašanje.
  4. C++ standard, ISO 14882:2003, odjeljak 1.9, fusnota 11.