Goto naredba

Из Википедије, слободне енциклопедије
Ilustracija upotrebe goto naredbe

Goto naredba. Ova naredba vrši bezuslovni prenos kontrole toka na odgovarajuće mesto u kodu obeleženo odgovarajućom labelom (koja ima oblik identifikatora). Za ovu naredbu skoka je pokazano da nije neophodna odnosno da se svaki program koji u sebi sadrži pomenutu naredbu može zameniti programom koji daje isti rezultat a ne koristi ovu naredbu vec koristi sekvencijalno izvršavanje naredbi, naredbe odlučivanja i jednu vrstu petlje (Teorema o strukturnom programiranju). U prošlosti je postojala ozbiljna naučna debata o upotrebi goto naredbe u programiranju.

Upotreba[уреди]

Goto naredba se obično koristi u kombinaciji sa If naredbom, koja može izazvati uslovni prenos kontrole. Programski jezici nameću razna ograničenja u odnosu na odredište Goto naredbe. Na primer, programski jezik C ne dozvoljava skok na etikete koje su sadržane u nekoj drugoj funkciji.

Teorema o strukturnom programiranju[уреди]

Strukturno programiranje je vid programiranja nastao sedamdesetih godina, a prethodilo mu je kompozitno programiranje. Tadašnje novonastale velike mogućnosti hardvera softver nije mogao da isprati, što je dovelo do prve softverske krize. 1968. godine holandski informatičar Edsher Dajkstra (Edsger Wybe Dijkstra) napisao je članak o štetnosti Goto naredbe u kojem je izneo zanimljivu činjenicu da je broj grešaka u softveru proporcionalan broju upotreba goto naredbe. Godinu dana kasnije, tačnije 1969. godine stvoren je programski jezik koji je omogućio pisanje programa bez pomenute goto naredbe. To je bio jezik Pascal (Niklaus Virt). Godine 1972. pojavila se knjiga "Strukturirano programiranje" (autora pomenutog Dijkstre, Hoara i Dahla)[1] u kojoj se nalaze članci vezani za rešavanje problema bez upotrebe ove naredbe. 1966. godine C. Boehm i G. Jakopini dokazali su teoremu o strukturnom programiranju (Böhm-Jacopini teorema): Svaki programski zadatak je moguće logički ostvariti primenom samo elementarnih struktura sekvence, izbora i ponavljanja. Primena ove teoreme nas dovodi do potrebe utvrđivanja metodologije razvoja programskih struktura. Najčešće se koristi top-down metoda.

Špageti kod[уреди]

Špageti kod je fraza koja se koristi za izvorni kod koji ima kompeksnu i zamršenu upravljačku strukturu, posebno onda kada koristi mnogo goto naredbi, izuzetaka i drugih "nestrukturnih" konstrukcija. Ime je dobrio baš po tome što je tok programa konceptualno kao činija špageta, uvrnut i zamršen. Špageti kod može nastati iz više razloga, kao na primer, neprekidne izmene od strane ljudi koji imaju različite stilove programiranja. Strukturno programiranje uveliko smanjuje učestalost špageti koda.

U nastavku sledi jedan trivijalni primer Špageti koda. Program štampa brojeve od 1 do 10, zajedno sa njihovim kvadratima. Uočimo da se uvlačenje ne koristi da bi se razlikovale različite akcije koje se izvršavaju, i da goto naredba zavisi od broja linija koda. Špageti kod u praksi je mnogo komplikovaniji i može u velikoj meri povećati troškove održavanja programa.

10 i = 0
20 i = i + 1
30 PRINT i; " Kvadrat broja je "; i * i
40 IF i >= 10 THEN GOTO 60
50 GOTO 20
60 PRINT "Program je završen."
70 END

Isti kod napisan u stilu strukturnog programiranja izgledao bi ovako:

10 FOR i = 1 TO 10
20 PRINT i; " Kvadrat broja je "; i * i
30 NEXT i
40 PRINT "Program je završen."
50 END

Prilikom upotrebe nižih programskih jezika i mašinskih jezika postoji velika opasnost pisanja špageti koda. S druge strane, usvajanjem istog režima kao i u strukturnom programiranju mogu se znatno poboljšati čitljivost i održavanje koda. Ovo se može postići, na primer, uvođenjem limita za upotrebu goto naredbi. Neki od široko korišćenih programskih jezika, kao što su Python i Java, nemaju goto naredbu, i stoga snažno podržavaju koncept strukturnog programiranja.

Istorija[уреди]

Goto naredba pojavila se još kod prvih viših progaramskih jezika. Iako je na sastanku vezanom za tada novonastali programski jezik Algol 1959. godine Heinz Zemanek eksplicitno bacio sumnju na neophodnost Goto naredbe, niko u to vreme nije obratio pažnju na njegovu opasku, uključujući i Edsger Dijkstra, koji će kasnije postati kultni protivnik Goto naredbe. 1970-ih i 1980-ih zabeležen je pad u korišćenju Goto naredbe što je išlo u korist paradigmi strukturnog programiranja, koja je dovela do špageti koda. Medjutim, uprkos svim lošim stranama Goto naredbe i velikom broju njenih protivnika ona se pojavila i u sintaksi jezika nove generacije, kao sto su C++ i Java, doduše u Javi je samo rezervisana reč goto ali se ne upotrebljava.


Pozitivne kritike[уреди]

Goto naredba kao takva nije naišla na veliki broj pozitivnih kritika. Ona svojom suštinom podseća na instrukcije koje se zadaju na asemblerskom nivou. Pozitivna strana ove naredbe jeste visok nivo kontrole koju programer dobija njenom upotrebom.

Negativne kritike[уреди]

Neki od standardnih stilova kodiranja ne preporučuju korišćenje Goto naredbe. Jedna od najpoznatijih kritika našla se upravo u pismu Edsger Dijkstra 1968. gde je tvrdio da neograničena Goto naredba treba biti ukinuta kod jezika višeg reda, jer komplikuje zadatak analiziranja i provere ispravnosti programa. Postojali su i oni koji su smatrali da je naredba skoka korisna, pa su u C program ubacili još dve naredbe skoka - Break i Continue. Drugi su, međutim, smatrali da su čak i varijacije poput break i return usred petlje jako loše i nepotrebne u praksi i baš iz tog razloga su se zalagali da postoji samo jedan izlaz iz petlje.

Primeri upotrebe[уреди]

U ovom pasusu nalaze se primeri upotrebe naredbe goto u raznim programskim jezicima.

Programski jezik C[уреди]

    #include<stdio.h>
 
    int main(){
      int x=10;

      PETLJA: do{
        if(x==13){
          x++;
          goto PETLJA;
        }

      printf("Vrednost promenljive x je : %d\n",x);
      x++;
      }while(x<=15);

      return 0;
    }

Programski jezik Java[уреди]

Programski jezik Java u svom spisku rezervisanih odnosno ključnih reči rezerviše reč goto, međutim ova reč još uvek nema svoju upotrebu u istom jeziku (oznacena jednom zvezdicom kao *not used u zvaničnoj dokumentaciji).

Programski jezik Delphi[уреди]

[2]

    var
      i : Integer;

    label
      GotoLabel;

    begin
      for i := 1 to 10 do
      begin
        ShowMessage('i = '+IntToStr(i));

        if i = 4 then Goto GotoLabel;   // Uslovni izlazak iz petlje
      end;

      ShowMessage('Petlja uspešno izvršena');
    GotoLabel:
      ShowMessage('Petlja završena sa i = '+IntToStr(i));
    end;

Programski jezik C++[уреди]

[3]

    # include <iostream>
    using namespace std;

    int main()
    {
        float num, average, sum = 0.0;
        int i, n;

        cout << "Maksimalni broj ulaza: ";
        cin >> n;

        for(i = 1; i <= n; ++i)
        {
            cout << "Unesi n" << i << ": ";
            cin >> num;
        
            if(num < 0.0)
            {
               // Kontrola toka na labelu skok
                goto skok;
            } 
            sum += num;
        }
    
    skok:
        average = sum / (i - 1);
        cout << "\nAverage = " << average;
        return 0;
    }

Programski jezik Pascal[уреди]

[4]

    program exGoto;
    label 1; 
    var
       a : integer;

    begin
       a := 10;
       (* Ponavljaj dok se petlja izvršava *)
       1: repeat
          if( a = 15) then
      
          begin
             (* Preskoči iteraciju *)
             a := a + 1;
             goto 1;
          end;
      
          writeln('value of a: ', a);
          a:= a +1;
       until a = 20;
    end.

Alterantive[уреди]

Strukturno programiranje[уреди]

Radi bolje jasnoće i efikasne optimizacije, jezici koji podržavaju strukturno prgramiranje (kao na primer Pascal) uveli su kontrole strukture kao što su:

  • procedure ili funkcije,
  • petlje (while, repeat until ili do, for naredba),
  • swich - case naredba, vrsta višestrukog grananja.

Ovi novi jezički mehanizmi zamenili su ekvivalentne tokove koju su se prethodno pisali upotrebom goto i if naredbi. Višestruko grananje zamenjuje goto naredbu u kojoj se instrukcija na koju treba preći određuje dinamički (uslovno).

Izuzeci[уреди]

U praksi, strogo pridržavanje osnovnog tri-strukturalnog šablona strukturnog programiranja, dovodi do visoko ugnježdenog koda i do nemogućnosti momentalnog izlaza iz strukturne jedinice.

Za ovaj problem postoje dva najčešće korišćena rešenja: način da se momentalno izađe iz strukturne jedinice i izuzeci. U oba slučaja kontrola se vraća na zatvarajuće blokove funkcije, a ne skače se na proizvoljnu lokaciju u kodu. Ovo je analogno upotrebi return naredbe. U C-u, naredbe break i continue dozvoljavaju da se petlja završi ili da se nastavi sa sledećom iteracijom, bez potrebe da dodatnom while ili if naredbom. U nekim jezicima moguća je upotreba break naredne na višestrukom nivou. Za rukovanje specijalnim situacijama dodate su konstrukcije za upravljanje izuzecima, kao što su try/catch/finally u programskom jeziku Java.

Mehanizam za upravljanje throw-catch izuzecima može, takođe, biti zloupotrebljen za pravljenje netransparentne upravljačke struktrure, baš kao i goto naredba.

Korutine[уреди]

Korutine dozvoljavaju ne samo višestruke tačke izlaza iz neke strukturne jedinice, već i višestruke ulaze, slično kao i goto naredba. Korutine su restriktivnije od goto naredbe, jer one mogu da nastave samo trenutno pokrenutu korutinu, i ne skaču na proizvolju liniju u kodu.

Continuation naredba[уреди]

Continuation naredba je slična goto naredbi po tome što vrši prenos kontrole sa proizvoljne tačke u programu na prethodno označenu tačku. Ova naredna je fleksibilnija od goto naredbe u jezicima koji je podržavaju, jer može preneti kontrolu izvan trenutne funkcije, a to goto naredbom nije moguće postići u mnogim strukturnim programskim jezicima.

Prenošenje poruka[уреди]

U neproceduralnim paradigmama, goto naredba je manje relevantna ili potpuno odsutna. Jedna od glavnih alternativa je "prenošenje poruka", koje je od posebnog značaja u paralelnom izračunavanju, međuprocesnoj komunikaciji i objektno orijentisanom programiranju. U ovim slučajevima, individualne komponente nemaju proizvoljni prenos kontrole, ali celokupna kontrola može biti preneta na komplikovaniji način.

Varijacije na temu[уреди]

Postoji mnoštvo različitih jezičkih konstrukcija pod klasom goto naredbe. U nastavku će biti opisane neke od najčešće korišćenih.

"Computed goto"[уреди]

U Fortranu, "computed goto" prenosi kontrolu na neku od labela navedenih u listi, na osnovu vrednosti izraza. Na primer: goto (20,30,40) i. Ekvivalentna konstrukcija u C-u je switch naredba, a u novoj verziji Fortrana case naredba je preporučena sintaksička alternativa. Programski jezik Basic koristi konstrukciju: on ... goto da postigne isti cilj.

"Assigned goto"[уреди]

U Fortranu takođe postoji i varijanta takozvane "assigned goto" naredbe koja prenosi kontrolu na labelu naredbe (broj linije) koja je sačuvana u (assigned to) celobrojnoj promenljivoj. Prelaz na celobrojnu promenljivu koja nije dodeljena nijednoj liniji koda, bio je nažalost moguć, i to je bio glavni izvor grešaka koje uključuju "аssigned goto" naredbe. U Fortranu, naredba assign jedino dozvoljava dodelu linije koda koja je konstantna (već postoji) celobrojnoj promenljivoj. Međutim, bilo je moguće da se ova promenljiva slučajno tretira kao celobrojna, na primer, inkrementiranjem koje rezultira neočekivanim ponašanjem goto naredbe. Sledeći primer demonstrira ponašanje "assigned goto" kada je linija i neodređena:

    assign 200 to i
    i = i+1
    goto i ! neočekivano ponašanje
200 write(*,*) "ovo je postojeći broj linije koda"

Nekoliko C kompajlera implementiralo je dve nestandardne C/C++ ekstenzije koje se odnose na goto, predstavljene su od strane gcc-a (GNU kolekcija kompajlera). Ova ekstenzija dozvoljava da adresa labele unutar trenutne funkcije bude dobijena kao void*, koristeći unarni operator &&. Goto naredba je proširena tako da dozvoljava prenos kontrole na proizvoljni void* izraz. U dokumentaciji C kompajlera ovo profirenje odnosi se na "computed goto". Kao i u standardnom goto u C-u, i u ovoj ekstenziji dozvoljeno je da goto prenosi kontrolu samo na linije unutar trenutne funkcije. Pokušaj prenosa izvan trenutne funkcije rezultira neočekivanim ponašanjem.

Podrške u programskim jezicima[уреди]

Mnogi jezici podržavaju goto naredbu, a ima i onih koji je ne podržavaju. U Javi, goto je rezervisana rec ali je neupotrebljiva, s obzirom da kompilacioni file.class generiše goto i labele.[5][6] Python ne podržava upotrebu goto naredbe, dok PHP nije podržavao goto sve do verzije 5.3. U C# postoji goto naredba. Takođe, moguće je dodati case i default labele. Goto case i Goto default često se koriste da zamene "fall-through" koji C# zabranjuje. C ima goto i obično se koristi u različitim idiomima, kao što je gore opisano.

Videti još[уреди]

Reference[уреди]

  1. Dijkstra, Edsger W. On a Somewhat Disappointing Correspondence (EWD-1009). E.W. Dijkstra Archive. Center for American History, University of Texas at Austin.  (original; transcription) (May, 1987)
  2. Delphi Basic
  3. Tutorijali jezik C++
  4. Primer goto upotrebe u Pascalu
  5. „The Java Language Specification, Third Edition”. »The keywords const and goto are reserved, even though they are not currently used. This may allow a Java compiler to produce better error messages if these C++ keywords incorrectly appear in programs.« 
  6. „The Java Language Specification, Third Edition”. »Unlike C and C++, the Java programming language has no goto statement; identifier statement labels are used with break (§14.15) or continue (§14.16) statements appearing anywhere within the labeled statement.« 

Literatura[уреди]