Mene

goto ( englanniksi  go to  - "go to") - ehdoton hyppyoperaattori (hyppää ohjelman tiettyyn kohtaan, joka ilmaistaan ​​rivinumerolla tai etiketillä) joissakin ohjelmointikielissä . Joillakin kielillä ehdottomalla haaraoperaattorilla voi olla eri nimi (esimerkiksi jmpkokoonpanokielillä ).

Toiminnallisuus

Käsky koostuu pääsääntöisesti gotokahdesta osasta: itse lauseesta ja ohjelman kohdehyppypisteen osoittavasta otsikosta: . Tunniste voi kielen säännöistä riippuen olla joko numero (kuten esimerkiksi klassisessa BASICissa) tai käytetyn ohjelmointikielen tunniste. Tunnisteetiketissä tarra sijoitetaan yleensä ennen lausetta, johon hypätään, ja erotetaan siitä kaksoispisteellä ( ). goto меткаметка:

Jump-käskyn toiminta on, että sen suorittamisen jälkeen suoritetaan seuraavat ohjelmakäskyt, jotka menevät tekstiin välittömästi otsikon jälkeen (seuraavaan hyppy-, haara- tai silmukkakäskyyn asti). Konekielillä hyppykäsky kopioituu prosessorirekisteriin , joka sisältää seuraavan suoritettavan käskyn osoitteen, etiketillä merkityn käskyn osoitteen.

Jakelu

Operaattori gotoon saatavana sellaisilla kielillä kuin Fortran , Algol , Cobol , BASIC , C ja C++ , C# , D , Pascal , Perl , Ada , PHP ja monet muut. Se on myös läsnä kaikilla kokoonpanokielillä (yleensä nimellä jmp, jumptai bra( englannin kielestä -  haara  )). Käyttövapaus gotovaihtelee kielittäin. Jos assemblerissä tai kielissä, kuten Fortranissa, sitä voidaan käyttää mielivaltaisesti (saa siirtää ohjausta ehdollisen operaattorin haaran sisällä tai silmukan tai proseduurin rungon sisällä), niin korkeamman tason kielissä sen käyttö on rajoitettu: pääsääntöisesti on gotokiellettyä siirtää ohjausta eri proseduurien ja funktioiden välillä käyttämällä valitun lausekelohkon sisällä, ehdollisen lauseen ja monivalintakäskyn haarojen välillä.

gotopuuttuu joissakin korkean tason kielissä (esim. Forth ). Pascalia goto ei alun perin ollut mukana, mutta saatavilla olevien kielityökalujen puute pakotti Niklaus Wirthin lisäämään sen. Myöhemmillä kielillään Wirth kuitenkin hylkäsi goto: tämä operaattori ei ole Moduuli-2 :ssa eikä Oberonissa ja Component Pascalissa . Javassa on varattu sana , gotomutta se ei sisällä toimintoja - kielessä ei ole ehdotonta hyppyoperaattoria (hyppy voidaan kuitenkin tehdä [1] ). Samalla kielessä on säilytetty tunnisteet - niillä voidaan poistua sisäkkäisistä silmukoista operaattorilla breakja continue.

Kritiikki

Korkean tason kielten operaattori gotoon kritiikin kohteena, koska sen liiallinen käyttö johtaa lukukelvottoman " spagettikoodin " syntymiseen. Tämä näkemys heijastui ensimmäisen kerran Edsger Dijkstran artikkelissa "Arguments against the GOTO-lausetta", [2] joka huomasi, että ohjelmakoodin laatu on kääntäen verrannollinen siinä olevien lauseiden määrään goto. Artikkeli tuli laajalti tunnetuksi sekä ohjelmoinnin teoreetikkojen että harjoittajien keskuudessa, minkä seurauksena näkemykset operaattorin käytöstä gotouudistuivat merkittävästi. Seuraavassa työssään Dijkstra perusteli sitä tosiasiaa, että koodilla ilman gotositä on paljon helpompi tarkistaa muodollinen oikeellisuus .

C-koodia gotoon vaikea muotoilla, koska se voi rikkoa suoritushierarkian ( strukturoitu ohjelmointiparadigma ) ja siksi ohjelman rakenteen näyttämiseen suunniteltuja sisennyksiä ei välttämättä aina ole asetettu oikein. gotohäiritsee myös ohjausrakenteiden kääntäjän optimointia . [3]

Jotkut käyttötavat gotovoivat aiheuttaa ongelmia ohjelman suorituslogiikassa:

Argumentit operaattoria vastaan goto​​osoittautuivat niin vakaviksi, että strukturoidussa ohjelmoinnissa niitä alettiin pitää erittäin ei-toivotuina. Tämä näkyi uusien ohjelmointikielten suunnittelussa. Se esimerkiksi gotokiellettiin Javassa ja Rubyssa . Useissa nykyaikaisissa kielissä se on silti jätetty tehokkuussyistä niissä harvoissa tapauksissa, joissa käyttö on gotoperusteltua. Joten se gotosäilytettiin Adassa  , joka on yksi historian arkkitehtuurin kannalta harkituimmista kielistä. [4] Kuitenkin niissä nykyaikaisissa korkean tason kielissä, joissa tämä operaattori on säilynyt, sen käyttöä koskevat pääsääntöisesti ankarat rajoitukset, jotka estävät sen vaarallisimpien sovellusmenetelmien käytön: esimerkiksi se on kiellettyä ohjata silmukan, menettelyn tai toiminnon ulkopuolelta. C++-kielistandardi kieltää muuttujan alustuksen ohittamisesta goto.

On muodollisesti todistettu ( Boehm-Jacopini -lause ), että sovellus gotoon valinnainen, eli ei ole olemassa sellaista ohjelmaa, gotojonka kanssa ei voitaisi kirjoittaa uudelleen täydellä toiminnallisuudella (mahdollisesti kuitenkin tehokkuuden menetyksellä).

Perusteltu käyttö

Käytännön ohjelmoinnissa käyttö gotokatsotaan joskus hyväksyttäväksi, kun muut kielityökalut eivät toteuta tai eivät toteuta tehokkaasti haluttua toiminnallisuutta.

Pääasiallinen sovellettavuuskriteeri on käytetyn ohjelmointiparadigmangoto rikkominen (alla olevissa esimerkeissä tämä on strukturoitua ohjelmointia ), muuten tulos on täynnä kaikenlaisia ​​sivuvaikutuksia ja vaikeasti löydettäviä virheitä.

Purkautuminen sisäkkäisistä silmukoista

Joillakin kielillä ei ole silmukan pääteoperaattoreita tai ne viittaavat vain sisäkkäiseen silmukkaan , jossa ne sijaitsevat (esimerkiksi C break:ssä continue). gotoUseista sisäkkäisistä silmukoista kerralla poistuminen yksinkertaistaa tässä tapauksessa huomattavasti ohjelmakoodia, jolloin ei tarvitse käyttää apulippumuuttujia ja ehdollisia lausekkeita .

Muita ratkaisuja tähän ongelmaan on laittaa sisäkkäiset silmukat erilliseen proseduuriin ja käyttää prosessin lopetuskäskyä, ja kielissä, joissa on poikkeustuki  , heittää poikkeus, jonka kahva sijaitsee silmukoiden ulkopuolella. Tällaiset ratkaisut ovat kuitenkin vähemmän tehokkaita toteutuksen ylimääräisten kustannusten vuoksi, varsinkin jos vastaavaa koodin osaa kutsutaan useita kertoja.

Esimerkki C++:ssa:

int matriisi [ n ][ m ]; int arvo ; ... for ( int i = 0 ; i < n ; ++ i ) for ( int j = 0 ; j < m ; ++ j ) if ( matriisi [ i ][ j ] == arvo ) { printf ( "arvo %d löytyi solusta (%d,%d) \n " , arvo , i , j ); //toimi jos löytyy goto end_loop ; } printf ( "arvoa %d ei löydy \n " , arvo ); //toimi jos ei löydy end_loop : ;

Yksinkertainen tapa päästä eroon goto siitä on luoda ylimääräinen lippumuuttuja, joka signaloi poistumaan uloimmasta silmukasta (sen jälkeen, kun olet poistunut sisäisestä silmukasta katkeamalla ) ja ohittaa koodilohkon, joka suoritetaan, kun arvoa ei löydy.

Muuttamatta koodin rakennetta ongelma ratkeaa, jos komennon break(tai sen vastaavan) avulla voit poistua useista sisäkkäisistä lohkoista kerralla, kuten Javassa tai Adassa . Java esimerkki:

int [][] matriisi ; int arvo ; ... ulkoinen : { for ( int i = 0 ; i < n ; i ++ ) for ( int j = 0 ; j < m ; j ++ ) if ( matriisi [ i ][ j ] == arvo ) { Järjestelmä . ulos . println ( "arvo " + arvo + " löytyi solusta (" + i + "," + j + ")" ); murtaa ulompi ; } Järjestelmä . ulos . println ( "arvo " + arvo + " ei löydy" ); }

Tyylikkäin tapa päästä ulos sisäkkäisestä silmukasta on PHP [5] . Komennon breakjälkeen voit määrittää poistuvien jaksojen määrän:

for ( $i = 0 ; $i < $Imax ; ++ $i ) { // ... for ( $j = 0 ; $j < $Jmax ; ++ $j ) { // ... if ( kunto ) tauko 2 ; // ... } // ... }

Virheiden käsittely

Jos kielellä ei ole poikkeusten käsittelytoimintoja , goto-käskyä voidaan käyttää koodin "normaalin" suorittamisen keskeyttämiseen ja lopulliseen koodiin vapauttamiseksi varatun muistin ja muiden lopullisten toimintojen avulla. Esimerkki C-kielellä:

int fn ( int * presult ) { int s = 0 ; TYPE entiteetti , other_entity = NULL ; TYYPPI2 entiteetti2 = NULL ; if ( ! ( entiteetti = luo_entiteetti ( ) ) ) { sts = ERROR_CODE1 ; Siirry exit0 ; } jos ( ! do_something ( entiteetti ) ) { sts = ERROR_CODE2 ; Goto exit1 ; } jos ( ehto ) { if ( ! ( entiteetti2 = luo_toinen_entiteetti ( ) ) ) { sts = ERROR_CODE3 ; Goto exit1 ; } if ( ( * presult = tee_toinen_asia ( entiteetti2 ) == NEGATIIVINEN ) { sts = ERROR_CODE4 ; goto exit2 ; } } muu { if ( ( * presult = tee_jotain_erityistä ( entiteetti ) == NEGATIIVINEN ) { sts = ERROR_CODE5 ; goto exit2 ; } } exit2 : if ( entiteetti2 ) tuhoa_toisen_entiteetti ( entiteetti2 ); exit1 : tuhota_entiteetti ( entiteetti ); exit0 : paluu s :t ; }

Ilman gotoa tällainen koodi olisi tarpeettomasti täynnä monia muita ehdollisia lausekkeita if.

Koodin luominen

Toinen käyttökelpoinen ehdottoman hypyn käyttö on automaattisesti luotu koodi, kuten ohjelmistotyökalujen luomat lekserit ja jäsentimet. Siten yacc , lex , bison -apuohjelmien luoma koodi on täynnä komentoja goto, mutta tätä koodia ei periaatteessa ole tarkoitettu ihmisen havainnointiin ja muokkaamiseen, ja sen oikeellisuuden määrää täysin sen luovan työkalun oikeellisuus.

Assembly - kielillä

Se on välttämätön operaattori ja sitä käytetään kaikkialla. Vuosien saatossa sen käytön intensiteetti ei ole muuttunut. Lisäksi useimmat laskenta-alustat tukevat myös niin tehokasta työkalua kuin indeksoitu ehdoton haara, joka mahdollistaa vähimmäisajan (useita konekäskyjä, jopa yksi) ohjauksen siirtämiseen yhteen monista alirutiineista, joiden valinta määräytyy sisällön mukaan. yhdestä prosessorirekisteristä. Tätä varten kaikkien tämän joukon rutiinien alkukohdat (sisääntulokohdat) on kuitenkin sijoitettava RAM -muistiin kiinteällä askeleella. Koska jälkimmäistä on vaikea toteuttaa korkean tason kielillä, indeksoitua ehdotonta hyppyä niissä ei yleensä ole, vaan se korvataan tehottomalla taulukkohaulla.

Muistiinpanot

  1. com.sun.org.apache.bcel.internal.generic: public class: GOTO . Haettu 6. elokuuta 2010. Arkistoitu alkuperäisestä 5. helmikuuta 2010.
  2. E. Dijkstra. Argumentteja goto-lausetta vastaan . Haettu 26. helmikuuta 2007. Arkistoitu alkuperäisestä 23. helmikuuta 2007.
  3. Donald Knuth. Jäsenneltyä ohjelmointia, jossa siirrytään lausuntoihin , jotka on arkistoitu alkuperäisestä 24. elokuuta 2009. 1974
  4. Code Complete: A Practical Handbook of Software Construction Arkistoitu 2. kesäkuuta 2017, Wayback Machine Redmond: Microsoft Press, 1993. 880 s.
  5. Syklin jatkaminen ja siitä poistuminen . Haettu 4. kesäkuuta 2015. Arkistoitu alkuperäisestä 22. toukokuuta 2015.

Linkit