Гото наредба

С Википедије, слободне енциклопедије
Илустрација употребе гото наредбе

Гото наредба. Ова наредба врши безусловни пренос контроле тока на одговарајуће место у коду обележено одговарајућом лабелом (која има облик идентификатора). За ову наредбу скока је показано да није неопходна односно да се сваки програм који у себи садржи поменуту наредбу може заменити програмом који даје исти резултат а не користи ову наредбу вец користи секвенцијално извршавање наредби, наредбе одлучивања и једну врсту петље (Теорема о структурном програмирању). У прошлости је постојала озбиљна научна дебата о употреби гото наредбе у програмирању.

Употреба[уреди | уреди извор]

Гото наредба се обично користи у комбинацији са Иф наредбом, која може изазвати условни пренос контроле. Програмски језици намећу разна ограничења у односу на одредиште Гото наредбе. На пример, програмски језик C не дозвољава скок на етикете које су садржане у некој другој функцији.

Теорема о структурном програмирању[уреди | уреди извор]

Структурно програмирање је вид програмирања настао седамдесетих година, а претходило му је композитно програмирање. Тадашње новонастале велике могућности хардвера софтвер није могао да испрати, што је довело до прве софтверске кризе. 1968. године холандски информатичар Едсхер Дајкстра (Edsger Wybe Dijkstra) написао је чланак о штетности Гото наредбе у којем је изнео занимљиву чињеницу да је број грешака у софтверу пропорционалан броју употреба гото наредбе. Годину дана касније, тачније 1969. године створен је програмски језик који је омогућио писање програма без поменуте гото наредбе. То је био језик Pascal (Niklaus Virt). Године 1972. појавила се књига "Структурирано програмирање" (аутора поменутог Дијкстре, Хоара и Дахла)[1] у којој се налазе чланци везани за решавање проблема без употребе ове наредбе. 1966. године C. Боехм и Г. Јакопини доказали су теорему о структурном програмирању (Böhm-Jacopini теорема): Сваки програмски задатак је могуће логички остварити применом само елементарних структура секвенце, избора и понављања. Примена ове теореме нас доводи до потребе утврђивања методологије развоја програмских структура. Најчешће се користи top-down метода.

Шпагети код[уреди | уреди извор]

Шпагети код је фраза која се користи за изворни код који има компексну и замршену управљачку структуру, посебно онда када користи много гото наредби, изузетака и других "неструктурних" конструкција. Име је добрио баш по томе што је ток програма концептуално као чинија шпагета, уврнут и замршен. Шпагети код може настати из више разлога, као на пример, непрекидне измене од стране људи који имају различите стилове програмирања. Структурно програмирање увелико смањује учесталост шпагети кода.

У наставку следи један тривијални пример Шпагети кода. Програм штампа бројеве од 1 до 10, заједно са њиховим квадратима. Уочимо да се увлачење не користи да би се разликовале различите акције које се извршавају, и да гото наредба зависи од броја линија кода. Шпагети код у пракси је много компликованији и може у великој мери повећати трошкове одржавања програма.

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

Исти код написан у стилу структурног програмирања изгледао би овако:

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

Приликом употребе нижих програмских језика и машинских језика постоји велика опасност писања шпагети кода. С друге стране, усвајањем истог режима као и у структурном програмирању могу се знатно побољшати читљивост и одржавање кода. Ово се може постићи, на пример, увођењем лимита за употребу гото наредби. Неки од широко коришћених програмских језика, као што су Python и Java, немају гото наредбу, и стога снажно подржавају концепт структурног програмирања.

Историја[уреди | уреди извор]

Гото наредба појавила се још код првих виших прогарамских језика. Иако је на састанку везаном за тада новонастали програмски језик Algol 1959. године Хеинз Земанек експлицитно бацио сумњу на неопходност Гото наредбе, нико у то време није обратио пажњу на његову опаску, укључујући и Едсгер Дијкстра, који ће касније постати култни противник Гото наредбе. 1970-их и 1980-их забележен је пад у коришћењу Гото наредбе што је ишло у корист парадигми структурног програмирања, која је довела до шпагети кода. Медјутим, упркос свим лошим странама Гото наредбе и великом броју њених противника она се појавила и у синтакси језика нове генерације, као сто су C++ и Java, додуше у Јави је само резервисана реч гото али се не употребљава.

Позитивне критике[уреди | уреди извор]

Гото наредба као таква није наишла на велики број позитивних критика. Она својом суштином подсећа на инструкције које се задају на асемблерском нивоу. Позитивна страна ове наредбе јесте висок ниво контроле коју програмер добија њеном употребом.

Негативне критике[уреди | уреди извор]

Неки од стандардних стилова кодирања не препоручују коришћење Гото наредбе. Једна од најпознатијих критика нашла се управо у писму Едсгер Дијкстра 1968. где је тврдио да неограничена Гото наредба треба бити укинута код језика вишег реда, јер компликује задатак анализирања и провере исправности програма. Постојали су и они који су сматрали да је наредба скока корисна, па су у C програм убацили још две наредбе скока - Break и Continue. Други су, међутим, сматрали да су чак и варијације попут break и return усред петље јако лоше и непотребне у пракси и баш из тог разлога су се залагали да постоји само један излаз из петље.

Примери употребе[уреди | уреди извор]

У овом пасусу налазе се примери употребе наредбе гото у разним програмским језицима.

Програмски језик 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;
    }

Програмски језик Java[уреди | уреди извор]

Програмски језик Java у свом списку резервисаних односно кључних речи резервише реч goto, међутим ова реч још увек нема своју употребу у истом језику (ознацена једном звездицом као *not used у званичној документацији).

Програмски језик 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;

Програмски језик 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;
    }

Програмски језик 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.

Алтерантиве[уреди | уреди извор]

Структурно програмирање[уреди | уреди извор]

Ради боље јасноће и ефикасне оптимизације, језици који подржавају структурно прграмирање (као на пример Pascal) увели су контроле структуре као што су:

  • процедуре или функције,
  • петље (while, repeat until или do, for наредба),
  • swich - case наредба, врста вишеструког гранања.

Ови нови језички механизми заменили су еквивалентне токове коју су се претходно писали употребом goto и if наредби. Вишеструко гранање замењује гото наредбу у којој се инструкција на коју треба прећи одређује динамички (условно).

Изузеци[уреди | уреди извор]

У пракси, строго придржавање основног три-структуралног шаблона структурног програмирања, доводи до високо угњежденог кода и до немогућности моменталног излаза из структурне јединице.

За овај проблем постоје два најчешће коришћена решења: начин да се моментално изађе из структурне јединице и изузеци. У оба случаја контрола се враћа на затварајуће блокове функције, а не скаче се на произвољну локацију у коду. Ово је аналогно употреби ретурн наредбе. У C-у, наредбе break и continue дозвољавају да се петља заврши или да се настави са следећом итерацијом, без потребе да додатном while или if наредбом. У неким језицима могућа је употреба break наредне на вишеструком нивоу. За руковање специјалним ситуацијама додате су конструкције за управљање изузецима, као што су try/catch/finally у програмском језику Java.

Механизам за управљање throw-catch изузецима може, такође, бити злоупотребљен за прављење нетранспарентне управљачке структруре, баш као и goto наредба.

Корутине[уреди | уреди извор]

Корутине дозвољавају не само вишеструке тачке излаза из неке структурне јединице, већ и вишеструке улазе, слично као и гото наредба. Корутине су рестриктивније од гото наредбе, јер оне могу да наставе само тренутно покренуту корутину, и не скачу на произвољу линију у коду.

Continuation наредба[уреди | уреди извор]

Continuation наредба је слична гото наредби по томе што врши пренос контроле са произвољне тачке у програму на претходно означену тачку. Ова наредна је флексибилнија од гото наредбе у језицима који је подржавају, јер може пренети контролу изван тренутне функције, а то гото наредбом није могуће постићи у многим структурним програмским језицима.

Преношење порука[уреди | уреди извор]

У непроцедуралним парадигмама, гото наредба је мање релевантна или потпуно одсутна. Једна од главних алтернатива је "преношење порука", које је од посебног значаја у паралелном израчунавању, међупроцесној комуникацији и објектно оријентисаном програмирању. У овим случајевима, индивидуалне компоненте немају произвољни пренос контроле, али целокупна контрола може бити пренета на компликованији начин.

Варијације на тему[уреди | уреди извор]

Постоји мноштво различитих језичких конструкција под класом гото наредбе. У наставку ће бити описане неке од најчешће коришћених.

"Computed goto"[уреди | уреди извор]

У Fortranu, "computed goto" преноси контролу на неку од лабела наведених у листи, на основу вредности израза. На пример: goto (20,30,40) i. Еквивалентна конструкција у C-у је switch наредба, а у новој верзији Fortrana case наредба је препоручена синтаксичка алтернатива. Програмски језик Basic користи конструкцију: on ... goto да постигне исти циљ.

"Assigned goto"[уреди | уреди извор]

У Фортрану такође постоји и варијанта такозване "assigned goto" наредбе која преноси контролу на лабелу наредбе (број линије) која је сачувана у (assigned to) целобројној променљивој. Прелаз на целобројну променљиву која није додељена ниједној линији кода, био је нажалост могућ, и то је био главни извор грешака које укључују "аssigned goto" наредбе. У Fortranu, наредба ассигн једино дозвољава доделу линије кода која је константна (већ постоји) целобројној променљивој. Међутим, било је могуће да се ова променљива случајно третира као целобројна, на пример, инкрементирањем које резултира неочекиваним понашањем гото наредбе. Следећи пример демонстрира понашање "assigned goto" када је линија i неодређена:

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

Неколико C компајлера имплементирало је две нестандардне C/C++ екстензије које се односе на гото, представљене су од стране гцц-а (ГНУ колекција компајлера). Ова екстензија дозвољава да адреса лабеле унутар тренутне функције буде добијена као void*, користећи унарни оператор &&. Гото наредба је проширена тако да дозвољава пренос контроле на произвољни void* израз. У документацији C компајлера ово профирење односи се на "цомпутед гото". Као и у стандардном гото у C-у, и у овој екстензији дозвољено је да гото преноси контролу само на линије унутар тренутне функције. Покушај преноса изван тренутне функције резултира неочекиваним понашањем.

Подршке у програмским језицима[уреди | уреди извор]

Многи језици подржавају гото наредбу, а има и оних који је не подржавају. У Јави, гото је резервисана рец али је неупотребљива, с обзиром да компилациони филе.цласс генерише гото и лабеле.[5][6] Python не подржава употребу гото наредбе, док PHP није подржавао гото све до верзије 5.3. У C# постоји гото наредба. Такође, могуће је додати case и default лабеле. Goto case и Goto default често се користе да замене "fall-through" који C# забрањује. C има гото и обично се користи у различитим идиомима, као што је горе описано.

Види још[уреди | уреди извор]

Референце[уреди | уреди извор]

  1. ^ Дијкстра, Едсгер W. Он а Сомеwхат Дисаппоинтинг Цорреспонденце (ЕWД-1009). Е.W. Дијкстра Арцхиве. Центер фор Америцан Хисторy, Университy оф Теxас ат Аустин.  (оригинал; трансцриптион) (Маy, 1987)
  2. ^ Делпхи Басиц
  3. ^ Туторијали језик C++
  4. ^ „Пример гото употребе у Пасцалу”. Архивирано из оригинала 7. 3. 2014. г. Приступљено 25. 11. 2016. 
  5. ^ „Тхе Јава Лангуаге Специфицатион, Тхирд Едитион”. „Тхе кеywордс цонст анд гото аре ресервед, евен тхоугх тхеy аре нот цуррентлy усед. Тхис маy аллоw а Јава цомпилер то продуце беттер еррор мессагес иф тхесе C++ кеywордс инцоррецтлy аппеар ин програмс. 
  6. ^ „Тхе Јава Лангуаге Специфицатион, Тхирд Едитион”. „Унлике C анд C++, тхе Јава программинг лангуаге хас но гото статемент; идентифиер статемент лабелс аре усед wитх бреак (§14.15) ор цонтинуе (§14.16) статементс аппеаринг анywхере wитхин тхе лабелед статемент. 

Литература[уреди | уреди извор]