Gå til

goto (fra engelsk  gå til  - "gå til") - en ubetinget springoperator (spring til et bestemt punkt i programmet, angivet med et linjenummer eller en etiket) i nogle programmeringssprog . På nogle sprog kan den ubetingede filialoperatør have et andet navn (f.eks. jmppå assemblersprog ).

Funktionalitet

Som regel gotobestår en sætning af to dele: selve sætningen og en etiket, der angiver målets springpunkt i programmet: . Etiketten kan, afhængigt af sprogets regler, enten være et tal (som f.eks. i klassisk BASIC) eller en identifikator for det anvendte programmeringssprog. For identifikatoretiketter placeres etiketten normalt før sætningen, der skal springes til og adskilles fra den med et kolon ( ). goto меткаметка:

Handlingen af ​​jump-sætningen er, at efter dens udførelse vil de næste programsætninger, der går i teksten umiddelbart efter etiketten (indtil næste jump-, branch- eller loop-sætning) blive udført. For maskinsprog kopieres springinstruktionen ind i processorregisteret, der indeholder adressen på den næste instruktion, der skal udføres, adressen på instruktionen markeret med etiketten.

Fordeling

Operatøren gotoer tilgængelig på sprog som Fortran , Algol , Cobol , BASIC , C og C++ , C# , D , Pascal , Perl , Ada , PHP og mange andre. Det er også til stede på alle samlesprog (normalt under navnet jmp, jumpeller bra(fra den engelske  filial  )). Brugsfriheden gotovarierer fra sprog til sprog. Hvis det i assemblers eller sprog som Fortran kan bruges vilkårligt (det er tilladt at overføre kontrol inde i en gren af ​​en betinget operatør eller inde i kroppen af ​​en loop eller procedure), så er dens brug på højere niveauer begrænset: som regel er det gotoforbudt at overføre kontrol mellem forskellige procedurer og funktioner ved at bruge inde i den valgte blok af sætninger, mellem grenene af den betingede sætning og multiple choice-sætningen.

gotofraværende på nogle sprog på højt niveau (f.eks. Forth ). Pascal goto var oprindeligt ikke inkluderet, men manglen på tilgængelige sprogværktøjer tvang Niklaus Wirth til at tilføje det. På sine senere sprog forlod Wirth stadig goto: denne operator er ikke i Modul-2 , heller ikke i Oberon og Component Pascal . Java har et reserveret ord goto , men det har ingen funktioner - der er ingen ubetinget springoperator i sproget (hoppet kan dog foretages [1] ). Samtidig er etiketter blevet bevaret i sproget - de kan bruges til at afslutte indlejrede løkker med operatorerne breakog continue.

Kritik

Operatøren gotopå højt niveau sprog er målet for kritik, da dens overdrevne brug fører til skabelsen af ​​ulæselig " spaghettikode ". Dette synspunkt blev først afspejlet i Edsger Dijkstras artikel "Arguments against the GOTO statement", [2] som bemærkede, at kvaliteten af ​​en programkode er omvendt proportional med antallet af udsagn gotoi den. Artiklen blev bredt kendt blandt både teoretikere og praktikere af programmering, som et resultat af, at syn på brugen af ​​operatøren gotoblev væsentligt revideret. I sit næste arbejde underbyggede Dijkstra det faktum, at for kode uden gotoer det meget lettere at kontrollere den formelle rigtighed af .

C-kode gotoer svær at formatere, da den kan bryde eksekveringshierarkiet ( struktureret programmeringsparadigme ), og derfor er indrykningerne designet til at vise programmets struktur muligvis ikke altid korrekt indstillet. gotoforstyrrer også compiler-optimeringer af kontrolstrukturer. [3]

Nogle anvendelser gotokan skabe problemer med programafviklingslogik:

Argumenterne mod operatøren gotoviste sig at være så alvorlige, at de i struktureret programmering begyndte at blive betragtet som yderst uønskede. Dette afspejlede sig i designet af nye programmeringssprog. For eksempel blev det gotoforbudt i Java og Ruby . I en række moderne sprog efterlades det stadig af effektivitetshensyn i de sjældne tilfælde, hvor brugen er gotoberettiget. Så det gotoblev bevaret i Ada  , et af de mest tankevækkende sprog med hensyn til arkitektur i historien. [4] Men i de moderne sprog på højt niveau, hvor denne operatør er blevet bevaret, er brugen af ​​den som regel underlagt strenge begrænsninger, der forhindrer brugen af ​​de farligste metoder til dens anvendelse: f.eks. er forbudt at passere kontrol udefra løkken, proceduren eller funktionen indenfor. C++ sprogstandarden forbyder at omgå variabel initialisering med goto.

Det er formelt bevist ( Boehm-Jacopini teorem ), at applikationen gotoer valgfri, det vil sige, at der ikke er et sådant program med goto, der ikke kunne omskrives uden det med fuld funktionalitet (dog muligvis med tab af effektivitet).

Berettiget brug

I praktisk programmering anses brugen gotonogle gange for acceptabel, når andre sprogværktøjer ikke implementerer eller ikke effektivt implementerer den ønskede funktionalitet.

Hovedkriteriet for anvendelighed gotoer ikke-krænkelse af det anvendte programmeringsparadigme (i eksemplerne nedenfor er dette struktureret programmering ), ellers er resultatet fyldt med alle mulige bivirkninger og svære at finde fejl.

Bryde ud af indlejrede sløjfer

Nogle sprog har ikke sløjfetermineringsoperatorer, eller de refererer kun til den indlejrede sløjfe , hvori de er placeret (for eksempel breaki continueC). Brug gotofor at afslutte flere indlejrede sløjfer på én gang i dette tilfælde forenkler programkoden betydeligt, hvilket eliminerer behovet for at bruge hjælpeflagvariabler og betingede sætninger .

Andre løsninger på dette problem er at sætte indlejrede løkker i en separat procedure og bruge en procedure-exit-sætning, og i sprog med undtagelsesstøtte  , smide en undtagelse, hvis håndtag er placeret uden for løkkerne. Sådanne løsninger er imidlertid mindre effektive på grund af implementeringsomkostninger, især hvis den tilsvarende kodesektion kaldes flere gange.

Eksempel i C++:

int matrix [ n ][ m ]; int værdi ; ... for ( int i = 0 ; i < n ; ++ i ) for ( int j = 0 ; j < m ; ++ j ) if ( matrix [ i ][ j ] == værdi ) { printf ( "værdi %d fundet i celle (%d,%d) \n " , værdi , i , j ); //act if found goto end_loop ; } printf ( "værdi %d ikke fundet \n " , værdi ); //act if not found end_loop : ;

En ligetil måde at slippe af med goto det er at oprette en ekstra flagvariabel, der signalerer at forlade den ydre sløjfe (efter at have forladt den indre sløjfe med break ) og omgå den kodeblok, der udføres, når værdien ikke findes.

Uden at ændre kodens struktur løses problemet, hvis kommandoen break(eller dens tilsvarende) giver dig mulighed for at forlade flere indlejrede blokke på én gang, som i Java eller Ada . Java eksempel:

int [][] matrix ; int værdi ; ... ydre : { for ( int i = 0 ; i < n ; i ++ ) for ( int j = 0 ; j < m ; j ++ ) if ( matrix [ i ][ j ] == værdi ) { System . ud . println ( "værdi " + værdi + " fundet i celle (" + i + "," + j + ")" ); bryde ydre ; } System . ud . println ( "værdi " + værdi + " ikke fundet" ); }

Den mest elegante måde at bryde ud af en indlejret løkke på er PHP [5] . Efter kommandoen breakkan du angive antallet af cyklusser, der skal forlades:

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

Fejlhåndtering

Hvis sproget ikke har faciliteter til håndtering af undtagelser , kan goto-sætningen bruges til at afbryde den "normale" udførelse af koden og springe til den endelige kode for at frigøre den optagede hukommelse og andre endelige handlinger. Eksempel på C-sprog:

int fn ( int * resultat ) { int m = 0 ; TYPE entity , another_entity = NULL ; TYPE2 enhed2 = NULL ; if ( ! ( entity = create_entity () )) ) { sts = ERROR_CODE1 ; gå til exit0 ; } hvis ( ! gør_noget ( entitet ) ) { sts = ERROR_CODE2 ; gå til exit1 ; } if ( betingelse ) { if ( ! ( entity2 = create_other_entity () ) ) { sts = ERROR_CODE3 ; gå til exit1 ; } if ( ( * presult = gør_anden_ting ( entitet2 ) == NEGATIV ) { sts = ERROR_CODE4 ; gå til exit2 ; } } andet { if ( ( * præsult = gør_noget_specielt ( enhed ) == NEGATIV ) { sts = ERROR_CODE5 ; gå til exit2 ; } } exit2 : hvis ( entitet2 ) ødelægge_en anden_entitet ( entitet2 ); exit1 : ødelægge_enhed ( entitet ); exit0 : returner m ; }

Uden goto ville en sådan kode være unødigt rodet med mange yderligere betingede udsagn if.

Kodegenerering

En anden gyldig brug af et ubetinget spring er kode, der genereres automatisk, såsom lexere og parsere genereret af softwareværktøjer. Således er koden genereret af yacc , lex , bison -værktøjerne fyldt med kommandoer goto, men denne kode er i princippet ikke beregnet til menneskelig opfattelse og redigering, og dens korrekthed bestemmes helt af korrektheden af ​​det værktøj, der skaber den.

assemblersprog

Det er en nødvendig operatør og bruges overalt. Gennem årene er der ingen ændring i intensiteten af ​​dets brug. Desuden understøtter de fleste computerplatforme også et så effektivt værktøj som en indekseret ubetinget gren, der tillader den minimale tid (flere maskininstruktioner, op til én) til at overføre kontrol til en af ​​de mange underrutiner, hvis valg er bestemt af indholdet af et af processorregistrene. Men til dette skal begyndelsen (indgangspunkter) af alle rutiner i dette sæt placeres i RAM med et fast trin. Da sidstnævnte er vanskeligt at implementere ved hjælp af sprog på højt niveau, er et indekseret ubetinget spring normalt ikke tilgængeligt i dem, det erstattes af en mindre effektiv tabelsøgning.

Noter

  1. com.sun.org.apache.bcel.internal.generic: offentlig klasse: GOTO . Hentet 6. august 2010. Arkiveret fra originalen 5. februar 2010.
  2. E. Dijkstra. Argumenter mod goto-erklæringen . Hentet 26. februar 2007. Arkiveret fra originalen 23. februar 2007.
  3. Donald Knuth. Struktureret programmering med gå til Statements Arkiveret fra originalen den 24. august 2009. 1974
  4. Code Complete: A Practical Handbook of Software Construction Arkiveret 2. juni 2017 på Wayback Machine Redmond: Microsoft Press, 1993. 880 s.
  5. Fortsættelse af cyklussen og afslutning af den . Hentet 4. juni 2015. Arkiveret fra originalen 22. maj 2015.

Links