Menj

goto (az angolból  go to  - "go to") - feltétel nélküli ugrás operátor (ugrás egy adott pontra a programban, amelyet sorszám vagy címke jelez) egyes programozási nyelveken . Egyes nyelveken a feltétel nélküli elágazás operátorának más neve is lehet (például jmpösszeállítási nyelveken ).

Funkcionalitás

Az utasítás gotoáltalában két részből áll: magából az utasításból és egy címkéből, amely a programban a cél ugráspontot jelzi: . A címke a nyelv szabályaitól függően lehet szám (mint például a klasszikus BASIC-ben), vagy a használt programozási nyelv azonosítója. Az azonosító címkék esetében a címkét általában az ugrandó utasítás elé helyezik, és kettősponttal ( ) választják el tőle .goto меткаметка:

A jump utasítás működése az, hogy végrehajtása után a következő programutasítások, amelyek közvetlenül a címke után kerülnek a szövegbe (a következő jump, elágazás vagy ciklus utasításig) végrehajtásra kerülnek. Gépi nyelveknél az ugrási utasítás a következő végrehajtandó utasítás címét tartalmazó processzorregiszterbe másolódik be, a címkével jelölt utasítás címét.

Elosztás

Az operátor gotoolyan nyelveken érhető el, mint a Fortran , Algol , Cobol , BASIC , C és C++ , C# , D , Pascal , Perl , Ada , PHP és még sokan mások. Ezenkívül minden összeállítási nyelven jelen van (általában néven jmp, jumpvagy bra(az angol  ágból  - ág)). A felhasználás szabadsága gotonyelvenként változó. Ha az assemblerekben vagy olyan nyelvekben, mint a Fortran, tetszőlegesen használható (engedélyezett a vezérlés átadása egy feltételes operátor ágán vagy egy ciklus vagy eljárás törzsén belül), akkor a magasabb szintű nyelvekben a használata korlátozott: főszabály szerint gototilos a vezérlés átadása a különböző eljárások és függvények között a kiválasztott utasításblokkon belül, a feltételes utasítás és a feleletválasztós utasítás ágai között.

gotohiányzik néhány magas szintű nyelvben (pl. Forth ). A Pascal goto eredetileg nem volt benne, de a rendelkezésre álló nyelvi eszközök hiánya miatt Niklaus Wirth kénytelen volt hozzáadni. Későbbi nyelvein Wirth még mindig elhagyta goto: ez az operátor nincs a Modul-2- ben, sem az Oberonban és a Component Pascalban . A Java -nak van egy fenntartott szava goto , de nem hordoz semmilyen funkciót - a nyelvben nincs feltétlen ugrásoperátor (az ugrás azonban elvégezhető [1] ). Ugyanakkor a címkék megmaradtak a nyelvben – ezek segítségével ki lehet lépni a beágyazott ciklusokból a breakés operátorokkal continue.

Kritika

A magas szintű nyelvek operátora a kritika célpontja, mivel túlzott használata olvashatatlan " spagetti kódgoto " létrehozásához vezet . Ezt a nézőpontot először Edsger Dijkstra "Érvek a GOTO utasítás ellen" című cikkében [2] tükrözte, aki észrevette, hogy egy programkód minősége fordítottan arányos a benne lévő állítások számával. A cikk széles körben ismertté vált a programozás teoretikusai és gyakorlói körében, aminek eredményeként az operátor használatával kapcsolatos nézetek jelentősen átdolgozásra kerültek. Következő munkájában Dijkstra alátámasztotta azt a tényt, hogy a kód nélküli kód esetében sokkal könnyebb ellenőrizni a formális helyességét . gotogotogoto

A C kódot gotonehéz formázni, mivel megtörheti a végrehajtási hierarchiát ( strukturált programozási paradigma ), és ezért előfordulhat, hogy a program szerkezetének megjelenítésére szolgáló behúzások nem mindig vannak megfelelően beállítva. gotozavarja a vezérlőstruktúrák fordítóoptimalizálását is . [3]

Egyes felhasználások gotoproblémákat okozhatnak a programvégrehajtási logikában:

Az üzemeltető elleni érvek gotoolyan súlyosnak bizonyultak, hogy a strukturált programozásban nagyon nemkívánatosnak tartották őket. Ez az új programozási nyelvek tervezésében is megmutatkozott. Például a Java és a Rubygoto nyelven betiltották . Számos modern nyelvben hatékonysági okokból még mindig meghagyják azokban a ritka esetekben, amikor a használata indokolt. Tehát Adában őrizték meg  , amely a történelem egyik legátgondoltabb nyelve az építészet szempontjából. [4] Azokon a modern, magas szintű nyelveken azonban, ahol ezt az operátort megőrizték, használata általában szigorú korlátozások alá esik, amelyek megakadályozzák a legveszélyesebb alkalmazási módok használatát: például tilos az irányítást a hurkon, eljáráson vagy funkción kívülről átadni. A C++ nyelvi szabvány tiltja a változó inicializálásának megkerülését . gotogotogoto

Formálisan bebizonyosodott ( Boehm-Jacopini tétel ), hogy az alkalmazás gotoopcionális, vagyis nincs olyan program, gotoamivel enélkül ne lehetne teljes funkcionalitással (de esetleg hatékonyságvesztéssel) átírni.

Indokolt használat

A gyakorlati programozásban a használat gotonéha elfogadhatónak tekinthető, ha más nyelvi eszközök nem, vagy nem valósítják meg hatékonyan a kívánt funkcionalitást.

Az alkalmazhatóság fő kritériuma az alkalmazott programozási paradigmagoto megsértése (az alábbi példákban ez a strukturált programozás ), különben az eredmény tele van mindenféle mellékhatással és nehezen fellelhető hibával.

Kitörés a beágyazott hurkokból

Egyes nyelvek nem rendelkeznek huroklezáró operátorral, vagy csak arra a beágyazott ciklusra utalnak , amelyben találhatók (például C- breakben continue). gotoEbben az esetben a több beágyazott ciklusból való kilépés egyszerre nagymértékben leegyszerűsíti a programkódot, és szükségtelenné teszi a segédjelző változók és feltételes utasítások használatát .

Más megoldás erre a problémára az, hogy beágyazott hurkokat helyez el egy külön eljárásba, és egy eljáráskilépési utasítást használ, és a kivételtámogatással rendelkező nyelveken olyan kivételt  dob, amelynek fogója a ciklusokon kívül található. Az ilyen megoldások azonban kevésbé hatékonyak a megvalósítási többletterhelés miatt, különösen, ha a megfelelő kódszakaszt többször hívják meg.

Példa C++ nyelven:

int mátrix [ n ][ m ]; int érték ; ... for ( int i = 0 ; i < n ; ++ i ) for ( int j = 0 ; j < m ; ++ j ) if ( mátrix [ i ][ j ] == érték ) { printf ( "%d érték található a cellában (%d,%d) \n " , érték , i , j ); //act if found goto end_loop ; } printf ( "%d érték nem található \n " , érték ); //act ha nem található end_loop : ;

Egy egyszerű módja annak, hogy megszabaduljunk goto tőle, ha létrehozunk egy további jelzőváltozót, amely jelzi a külső hurokból való kilépést (miután kilép a belső hurokból break -vel ), és megkerüli azt a kódblokkot, amely akkor fut le, ha az érték nem található.

A kód szerkezetének megváltoztatása nélkül a probléma megoldódik, ha a parancs break(vagy annak megfelelője) lehetővé teszi, hogy egyszerre több beágyazott blokkból lépjen ki, mint például a Java vagy az Ada esetében . Java példa:

int [][] mátrix ; int érték ; ... külső : { for ( int i = 0 ; i < n ; i ++ ) for ( int j = 0 ; j < m ; j ++ ) if ( mátrix [ i ][ j ] == érték ) { Rendszer . ki . println ( "érték " + érték + " cellában található (" + i + "," + j + ")" ); külső törése ; } Rendszer . ki . println ( "érték " + érték + " nem található" ); }

A beágyazott ciklusból a legelegánsabb módja a PHP [5] . A parancs után breakmegadhatja a távozni kívánt ciklusok számát:

for ( $i = 0 ; $i < $Imax ; ++ $i ) { // ... for ( $j = 0 ; $j < $Jmax ; ++ $j ) { // ... if ( feltétel ) 2. szünet ; // ... } // ... }

Hibakezelés

Ha a nyelv nem rendelkezik kivételkezelési lehetőségekkel , akkor a goto utasítással megszakítható a kód "normális" végrehajtása, és a végső kódra ugorhat a foglalt memória és egyéb végső műveletek felszabadítása érdekében. Példa C nyelven:

int fn ( int * presult ) { int sts = 0 ; TYPE entitás , másik_entitás = NULL ; TYPE2 entitás2 = NULL ; if ( ! ( entitás = entitás létrehozása ( ) ) ) { sts = ERROR_CODE1 ; kilép0 ; _ } if ( ! do_something ( entitás ) ) { sts = ERROR_CODE2 ; kilép1 ; _ } if ( feltétel ) { if ( ! ( entitás2 = másik_entitás létrehozása ( ) ) ) { sts = ERROR_CODE3 ; kilép1 ; _ } if ( ( * presult = do_anther_thing ( entitás2 ) == NEGATÍV ) { sts = ERROR_CODE4 ; goto exit2 ; } } másik { if ( ( * presult = do_something_special ( entitás ) == NEGATÍV ) { sts = ERROR_CODE5 ; goto exit2 ; } } exit2 : if ( entitás2 ) semmisít_másik_entitás ( entitás2 ); exit1 : megsemmisít_entitás ( entitás ); exit0 : sts visszatérése ; }

Goto nélkül egy ilyen kód szükségtelenül tele lenne sok további feltételes utasítással if.

Kódgenerálás

A feltétel nélküli ugrás másik érvényes módja az automatikusan generált kód, például a szoftvereszközök által generált lexerek és értelmezők. Így a yacc , lex , bison segédprogramok által generált kód tele van parancsokkal goto, de ez a kód elvileg nem emberi észlelésre és szerkesztésre szolgál, helyességét pedig teljes mértékben az azt létrehozó eszköz helyessége határozza meg.

Assembly nyelveken

Szükséges operátor, és mindenhol használják. Az évek során nem változott a használat intenzitása. Sőt, a legtöbb számítástechnikai platform egy olyan hatékony eszközt is támogat, mint az indexelt feltétel nélküli ág, amely lehetővé teszi a minimális idő (több gépi utasítás, legfeljebb egy) átadását a számos szubrutin egyikére, amelyek kiválasztását a tartalom határozza meg. az egyik processzorregiszterből. Ehhez azonban ebben a halmazban az összes rutin kezdetét (belépési pontját) fix lépéssel a RAM -ban kell elhelyezni. Mivel utóbbiak magas szintű nyelvek segítségével nehezen kivitelezhetők, bennük általában nem érhető el indexelt feltétel nélküli ugrás, helyette egy kevésbé hatékony táblakeresés.

Jegyzetek

  1. com.sun.org.apache.bcel.internal.generic: public class: GOTO . Letöltve: 2010. augusztus 6. Az eredetiből archiválva : 2010. február 5..
  2. E. Dijkstra. Érvek a goto kijelentés ellen . Letöltve: 2007. február 26. Az eredetiből archiválva : 2007. február 23..
  3. Donald Knuth. Strukturált programozás a 2009. augusztus 24-i eredetiből archivált nyilatkozatokkal. 1974
  4. Code Complete: A Practical Handbook of Software Construction Archivált : 2017. június 2., a Wayback Machine Redmond: Microsoft Press, 1993. 880. o.
  5. A ciklus folytatása és kilépés belőle . Letöltve: 2015. június 4. Az eredetiből archiválva : 2015. május 22.

Linkek