Goto

This article is about the programming statement in high-level languages. For other uses, see Goto (disambiguation).

Goto (goto, GOTO, GO TO or other case combinations, depending on the programming language) is a statement found in many computer programming languages. It performs a one-way transfer of control to another line of code; in contrast a function call normally returns control. The jumped-to locations are usually identified using labels, though some languages use line numbers. At the machine code level, a goto is a form of branch or jump statement. Many languages support the goto statement, and many do not (see language support).

The structured program theorem proved that the goto statement is not necessary to write programs; some combination of the three programming constructs of sequence, selection/choice, and repetition/iteration are sufficient for any computation that can be performed by a Turing machine, with the caveat that code duplication and additional variables may need to be introduced.[1] At machine code level, goto is used to implement the structured programming constructs.

In the past there was considerable debate in academia and industry on the merits of the use of goto statements. Use of goto was formerly common, but since the advent of structured programming in the 1960s and 1970s its use has declined significantly. The primary criticism is that code that uses goto statements is harder to understand than alternative constructions. Goto remains in use in certain common usage patterns, but alternatives are generally used if available. Debates over its (more limited) uses continue in academia and software industry circles.

Usage

goto label

The goto statement is often combined with the if statement to cause a conditional transfer of control.

IF condition THEN goto label

Programming languages impose different restrictions with respect to the destination of a goto statement. For example, the C programming language does not permit a jump to a label contained within another function,[2] however jumps within a single call chain are possible using the setjmp/longjmp functions.

Criticism

Although at the pre-ALGOL meeting held in 1959, Heinz Zemanek explicitly threw doubts on the necessity of GOTO statements, at the time no one paid attention to his remark, including Edsger Dijkstra, who would later become the iconic opponent of GOTO.[3] The 1970s and 1980s saw a decline in the use of GOTO statements in favor of the "structured programming" paradigm, with goto criticized as leading to "unmaintainable spaghetti code" (see below). Some programming style coding standards, for example the Gnu Pascal Coding Standards, recommend against the use of GOTO statements. The Böhm-Jacopini proof (1966) did not settle the question of whether to adopt structured programming for software development, partly because the construction was more likely to obscure a program than to improve it because its application requires the introduction of additional local variables.[4] It has, however, sparked a prominent debate among computer scientists, educators, language designers and application programmers that saw a slow but steady shift away from the formerly ubiquitous use of the GOTO. Probably the most famous criticism of GOTO is a 1968 letter by Edsger Dijkstra called Go To Statement Considered Harmful.[3] [5] In that letter Dijkstra argued that unrestricted GOTO statements should be abolished from higher-level languages because they complicated the task of analyzing and verifying the correctness of programs (particularly those involving loops). The letter itself sparked a debate, including a "'GOTO Considered Harmful' Considered Harmful" letter[6] sent to Communications of the ACM (CACM) in March 1987, as well as further replies by other people, including Dijkstra's On a Somewhat Disappointing Correspondence.[7]

An alternative viewpoint is presented in Donald Knuth's Structured Programming with go to Statements, which analyzes many common programming tasks and finds that in some of them GOTO is the optimal language construct to use.[8] In their quasi-standard book on the C programming language, Dennis Ritchie and Brian Kernighan warn that goto is "infinitely abusable", but also suggest that it could be used for end-of-function error handlers and for multi-level breaks from loops.[9] These two patterns can be found in numerous subsequent books on C by other authors;[10][11][12][13] a 2007 introductory textbook notes that the error handling pattern is a way to work around the "lack of built-in exception handling within the C language".[10] Other programmers, such as Linux Kernel designer and coder Linus Torvalds or software engineer and book author Steve McConnell, also object to Dijkstra's point of view, stating that GOTOs can be a useful language feature, improving program speed, size and code clearness, but only when used in a sensible way by a comparably sensible programmer.[14][15] According to computer science professor John Regehr, in 2013, there were about 100,000 instances of goto in the Linux kernel code.[16]

Other academics took the completely opposite viewpoint and argued that even instructions like break and return from the middle of loops are bad practice as they are not needed in the Böhm-Jacopini result, and thus advocated that loops should have a single exit point.[17] For instance, Bertrand Meyer wrote in his 2009 textbook that instructions like break and continue "are just the old goto in sheep's clothing".[18] A slightly modified form of the Böhm-Jacopini result allows however the avoidance of additional variables in structured programming, as long as multi-level breaks from loops are allowed.[19] Because some languages like C don't allow multi-level breaks via their break keyword, some textbooks advise the programmer to use goto in such circumstances.[13] The MISRA C 2004 standard bans goto, continue, as well as multiple return and break statements.[20] The 2012 edition of the MISRA C standard has downgraded the prohibition on goto from "required" to "advisory" status; the 2012 edition has an additional, mandatory rule that prohibits only backward, but not forward jumps with goto.[21][22]

Fortran introduced structured programming constructs in 1978 and in successive revisions the relatively loose semantic rules governing the allowable use of goto were tightened; the "extended range" in which a programmer could use a GOTO to enter and leave a still-executing DO loop was removed from the language in 1978,[23] and by 1995 several forms of Fortran GOTO, including the Computed GOTO and the Assigned GOTO, had been deleted from the language.[24] Some widely used modern programming languages, such as Java and Python lack the GOTO statement – see language support – though most provide some means of breaking out of a selection, or either breaking out of or moving on to the next step of an iteration. The viewpoint that disturbing the control flow in code is undesirable may be seen in the design of some programming languages, for instance Ada[25] visually emphasizes label definitions using angle brackets.

Entry 17.10 in comp.lang.c FAQ list[26] addresses the issue of GOTO use directly, stating

Programming style, like writing style, is somewhat of an art and cannot be codified by inflexible rules, although discussions about style often seem to center exclusively around such rules. In the case of the goto statement, it has long been observed that unfettered use of goto's quickly leads to unmaintainable spaghetti code. However, a simple, unthinking ban on the goto statement does not necessarily lead immediately to beautiful programming: an unstructured programmer is just as capable of constructing a Byzantine tangle without using any goto's (perhaps substituting oddly-nested loops and Boolean control variables, instead). Many programmers adopt a moderate stance: goto's are usually to be avoided, but are acceptable in a few well-constrained situations, if necessary: as multi-level break statements, to coalesce common actions inside a switch statement, or to centralize cleanup tasks in a function with several error returns. (...) Blindly avoiding certain constructs or following rules without understanding them can lead to just as many problems as the rules were supposed to avert. Furthermore, many opinions on programming style are just that: opinions. They may be strongly argued and strongly felt, they may be backed up by solid-seeming evidence and arguments, but the opposing opinions may be just as strongly felt, supported, and argued. It's usually futile to get dragged into "style wars", because on certain issues, opponents can never seem to agree, or agree to disagree, or stop arguing.

Common usage patterns of Goto

While overall usage of gotos has been declining, there are still situations in some languages where a goto provides the shortest and most straightforward way to express program's logic (while it's possible to express the same logic without gotos, the equivalent code will be longer and often more difficult to understand). In other languages, there are structured alternatives, notably exceptions and tail calls.

Situations in which goto is often useful include:

These uses are relatively common in C, but much less common in C++ or other languages with higher-level features.[34] However, throwing and catching an exception inside a function can be extraordinarily inefficient in some languages; a prime example is Objective-C, where a goto is a much faster alternative.[36]

Another use of goto statements is to modify poorly factored legacy code, where avoiding a goto would require extensive refactoring or code duplication. For example, given a large function where only certain code is of interest, a goto statement allows one to jump to or from only the relevant code, without otherwise modifying the function. This usage is considered code smell, but finds occasional use.

Alternatives

Structured programming

In classical structured programming, three basic structures are used: sequence, repetition, and selection. Sequence is the execution of one program unit following another; repetition is the repeated execution of the same program unit until a desired program state is reached; and selection is the executing of one and only one of a fixed set of possible alternative program units depending on the program state. Here typically the "program unit" is a compound statement constructed in turn using the three basic structures.

Although these three control structures can all be hand-coded using gotos and ifs, the desire for clarity and efficient optimization led to the introduction and refinement of supporting structures such as (in Pascal) procedure and function blocks, while, repeat until, and for statements, and case statements (a form of multiway branching, replacing computed goto).

Exceptions

Further information: Exception handling

In practice, a strict adherence to the basic three-structure template of structured programming yields highly nested code, due to inability to exit a structured unit prematurely, and a combinatorial explosion with quite complex program state data to handle all possible conditions.

Two solutions have been generally adopted: a way to exit a structured unit prematurely, and more generally exceptions – in both cases these go up the structure, returning control to enclosing blocks or functions, but do not jump to arbitrary code locations. These are analogous to the use of a return statement in non-terminal position – not strictly structured, due to early exit, but a mild relaxation of the strictures of structured programming. In C, break and continue allow one to terminate a loop or continue to the next iteration, without requiring an extra while or if statement. In some languages multi-level breaks are also possible. For handling exceptional situations, specialized exception handling constructs were added, such as try/catch/finally in Java.

The throw-catch exception handling mechanisms can also be easily abused to create non-transparent control structures, just like goto can be abused.[37]

Tail calls

Main article: Tail call

In a paper delivered to the ACM conference in Seattle in 1977, Guy L. Steele summarized the debate over the GOTO and structured programming, and observed that procedure calls in the tail position of a procedure can be most optimally treated as a direct transfer of control to the called procedure, typically eliminating unnecessary stack manipulation operations.[38] Since such "tail calls" are very common in Lisp, a language where procedure calls are ubiquitous, this form of optimization considerably reduces the cost of a procedure call compared to the GOTO used in other languages. Steele argued that poorly implemented procedure calls had led to an artificial perception that the GOTO was cheap compared to the procedure call. Steele further argued that "in general procedure calls may be usefully thought of as GOTO statements which also pass parameters, and can be uniformly coded as machine code JUMP instructions", with the machine code stack manipulation instructions "considered an optimization (rather than vice versa!)".[38] Steele cited evidence that well optimized numerical algorithms in Lisp could execute faster than code produced by then-available commercial Fortran compilers because the cost of a procedure call in Lisp was much lower. In Scheme, a Lisp dialect developed by Steele with Gerald Jay Sussman, tail call optimization is mandatory.[39]

Although Steele's paper did not introduce much that was new to computer science, at least as it was practised at MIT, it brought to light the scope for procedure call optimization, which made the modularity-promoting qualities of procedures into a more credible alternative to the then-common coding habits of large monolithic procedures with complex internal control structures and extensive state data. In particular, the tail call optimizations discussed by Steele turned the procedure into a credible way of implementing iteration through single tail recursion (tail recursion calling the same function). Further, tail call optimization allows mutual recursion of unbounded depth, assuming tail calls – this allows transfer of control, as in finite state machines, which otherwise is generally accomplished with goto statements.

Coroutines

Main article: Coroutine

Coroutines are a more radical relaxation of structured programming, allowing not only multiple exit points (as in returns in non-tail position), but also multiple entry points, similar to goto statements. Coroutines are more restricted than goto, as they can only resume a currently running coroutine at specified points – continuing after a yield – rather than jumping to an arbitrary point in the code. A limited form of coroutines are generators, which are sufficient for some purposes. Even more limited are closures – subroutines which maintain state (via static variables), but not execution position. A combination of state variables and structured control, notably an overall switch statement, can allow a subroutine to resume execution at an arbitrary point on subsequent calls, and is a structured alternative to goto statements in the absence of coroutines; this is a common idiom in C, for example.

Continuations

Main article: Continuation

A continuation is similar to a GOTO in that it transfers control from an arbitrary point in the program to a previously marked point. A continuation is more flexible than GOTO in those languages that support it, because it can transfer control out of the current function, something that a GOTO cannot do in most structured programming languages. In those language implementations that maintain stack frames for storage of local variables and function arguments, executing a continuation involves adjusting the program's call stack in addition to a jump. The longjmp function of the C programming language is an example of an escape continuation that may be used to escape the current context to a surrounding one. The Common Lisp GO operator also has this stack unwinding property, despite the construct being lexically scoped, as the label to be jumped to can be referenced from a closure.

In Scheme, continuations can even move control from an outer context to an inner one if desired. This almost limitless control over what code is executed next makes complex control structures such as coroutines and cooperative multitasking relatively easy to write.[40]

Message passing

Main article: Message passing

In non-procedural paradigms, goto is less relevant or completely absent. One of the main alternatives is message passing, which is of particular importance in concurrent computing, interprocess communication, and object oriented programming. In these cases, the individual components do not have arbitrary transfer of control, but the overall control may be scheduled in complex ways, such as via preemption. The influential languages Simula and Smalltalk were among the first to introduce the concepts of messages and objects. By encapsulating state data, object-oriented programming reduced software complexity to interactions (messages) between objects.

Variations

There are a number of different language constructs under the class of goto statements.

Computed GOTO and Assigned GOTO

See also: Branch table

In FORTRAN, a computed GOTO jumps to one of several labels in a list, based on the value of an expression. An example is goto (20,30,40) i. The equivalent construct in C is the switch statement statement and in newer Fortran a CASE statement is the recommend syntactical alternative.[41] BASIC has the ON ... GOTO construct that achieves the same goal.[42]

Fortran also had an assigned goto variant that transfers control to a statement label (line number) which is stored in (assigned to) an integer variable. Jumping to an integer variable that had not been ASSIGNEd to was unfortunately possible, and was a major source of bugs involving assigned gotos.[43] The Fortran assign statement only allows a constant (existing) line number to be assigned to the integer variable. However, it was possible to accidentally treat this variable as an integer thereafter, for example increment it, resulting in unspecified behavior at goto time, like the following code demonstrates, in which the behavior of the goto i line is unspecified:[44]

    assign 200 to i
    i = i+1
    goto i ! unspecified behavior
200 write(*,*) "this is valid line number"

Several C compilers implement two non-standard C/C++ extensions relating to gotos originally introduced by gcc.[45][46] The GNU extension allows the address of a label inside the current function to be obtained as a void* using the unary, prefix label value operator &&. The goto instruction is also extended to allow jumping to an arbitrary void* expression. This C extension is referred to as a computed goto in documentation of the C compilers that support it; its semantics are a superset of Fortran's assigned goto, because it allows arbitrary pointer expressions as the goto target, while Fortran's assigned goto doesn't allow arbitrary expressions as jump target.[47] As with the standard goto in C, the GNU C extension allows the target of the computed goto to reside only in the current function. Attempting to jump outside the current function results in unspecified behavior.[47]

Some variants of BASIC also support a computed GOTO in the sense used in GNU C, i.e. in which the target can be any line number, not just one from a list. For example, in MTS BASIC one could write GOTO i*1000 to jump to the line numbered 1000 times the value of a variable i (which might represent a selected menu option, for example).[48]

ALTER

Up to the 1985 ANSI COBOL standard had the ALTER verb which could be used to change the destination of an existing GO TO, which had to be in a paragraph by itself.[49] The feature, which allowed polymorphism, was frequently condemned and seldom used.[50]

Perl GOTO

In Perl, there is a variant of the goto statement that is not a traditional GOTO statement at all. It takes a function name and transfers control by effectively substituting one function call for another (a tail call): the new function will not return to the GOTO, but instead to the place from which the original function was called.[51]

Emulated GOTO

There are several programming languages that do not support GOTO by default. By using GOTO emulation, it is still possible to use GOTO in these programming languages, albeit with some restrictions. One can emulate GOTO in Java,[52] JavaScript,[53] and Python.[54]

PL/I label variables

PL/I has the data type LABEL, which can be used to implement both the "assigned goto" and the "computed goto." PL/I allows branches out of the current block. A calling procedure can pass a label as an argument to a called procedure which can then exit with a branch.

 /* This implements the equivalent of */
 /* the assigned goto                 */
   declare where label;
   where = somewhere;
   goto where;
   ...
 somewhere: /* statement */ ;
   ...
 /* This implements the equivalent of */
 /* the computed goto                 */
   declare where (5) label;
   declare inx fixed;
   where(1) = abc;
   where(2) = xyz;
   ...
   goto where(inx);
   ...
 abc: /* statement */ ;
   ...
 xyz: /* statement */ ;
   ...

Language support

Many languages support the goto statement, and many do not. In Java, goto is a reserved word, but is unusable, although the compiled file.class generates GOTOs and LABELs.[55][56] Python does not have support for goto, other than in the joke module goto. In PHP there was no native support for goto until version 5.3 (libraries were available to emulate its functionality).[57]

C has goto, and it is commonly used in various idioms, as discussed above.

Functional programming languages such as Scheme generally do not have goto, instead using continuations.

See also

References

  1. David Anthony Watt; William Findlay (2004). Programming language design concepts. John Wiley & Sons. p. 228. ISBN 978-0-470-85320-7.
  2. C Standard section 6.8.6.1 The goto statement
  3. 3.0 3.1 Dijkstra 1968.
  4. Kenneth Louden, Lambert (2011). Programming Languages: Principles and Practices. Cengage Learning. p. 422. ISBN 1-111-52941-8.
  5. EWD 215: A Case against the GO TO Statement
  6. Frank Rubin (March 1987). ""GOTO Considered Harmful" Considered Harmful" (PDF). Communications of the ACM 30 (3): 195–196. doi:10.1145/214748.315722. Archived from the original (PDF) on 2009-03-20.
  7. 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)
  8. Donald Knuth (1974). "Structured Programming with go to Statements" (PDF). Computing Surveys 6 (4): 261–301. doi:10.1145/356635.356640.
  9. Brian W. Kernighan; Dennis Ritchie (1988). C Programming Language (2nd ed.). Prentice Hall. pp. 60–61. ISBN 978-0-13-308621-8.
  10. 10.0 10.1 10.2 Michael A. Vine (2007). C Programming for the Absolute Beginner. Cengage Learning. p. 262. ISBN 1-59863-634-0.
  11. Sandra Geisler (2011). C All-in-One Desk Reference For Dummies. John Wiley & Sons. pp. 217–220. ISBN 978-1-118-05424-6.
  12. Stephen Prata (2013). C Primer Plus. Addison-Wesley. pp. 287–289. ISBN 978-0-13-343238-1.
  13. 13.0 13.1 13.2 13.3 Sartaj Sahni; Robert F. Cmelik; Bob Cmelik (1995). Software Development in C. Silicon Press. p. 135. ISBN 978-0-929306-16-2.
  14. http://kerneltrap.org/node/553
  15. "Code Complete, First Edition". Stevemcconnell.com. Retrieved 2014-07-22.
  16. Use of Goto in Systems Code
  17. Roberts, E. [1995] “Loop Exits and Structured Programming: Reopening the Debate,” ACM SIGCSE Bulletin, (27)1: 268–272.
  18. Bertrand Meyer (2009). Touch of Class: Learning to Program Well with Objects and Contracts. Springer Science & Business Media. p. 189. ISBN 978-3-540-92144-8.
  19. Dexter Kozen and Wei-Lung Dustin Tseng. "The Böhm–Jacopini Theorem Is False, Propositionally" (PDF). MPC 2008. doi:10.1007/978-3-540-70594-9_11.
  20. "Why "continue" is considered as a C violation in MISRA C:2004?". Stack Overflow. 2012-06-11. Retrieved 2014-07-22.
  21. Mark Pitchford and Chris Tapp (2013-02-25). "MISRA C:2012: Plenty Of Good Reasons To Change". Electronic Design. Retrieved 2014-07-22.
  22. Tom Williams (March 2013). "Checking Rules for C: Assuring Reliability and Safety". RTC Magazine. Retrieved 2014-07-22.
  23. ANSI X3.9-1978. American National Standard – Programming Language FORTRAN. American National Standards Institute. Also known as ISO 1539-1980, informally known as FORTRAN 77
  24. ISO/IEC 1539-1:1997. Information technology – Programming languages – Fortran – Part 1: Base language. Informally known as Fortran 95. There are a further two parts to this standard. Part 1 has been formally adopted by ANSI.
  25. John Barnes (2006-06-30). Programming in Ada 2005. Addison Wesley. p. 114115. ISBN 0-321-34078-7.
  26. "Question 17.10". C-faq.com. Retrieved 2014-07-22.
  27. 27.0 27.1 Linux: Using goto In Kernel Code
  28. 28.0 28.1 https://www.kernel.org/doc/Documentation/CodingStyle
  29. "Branching Statements (The Java™ Tutorials > Learning the Java Language > Language Basics)". Docs.oracle.com. 2012-02-28. Retrieved 2014-07-22.
  30. "The Java Language Environment". Oracle.com. Retrieved 2014-07-22.
  31. Brender, Ronald F. (2002). "The BLISS programming language: a history" (PDF). Software: Practice and Experience 32 (10): 955–981. doi:10.1002/spe.470.
  32. 32.0 32.1 Diomidis Spinellis (27 May 2003). Code Reading: The Open Source Perspective. Addison-Wesley Professional. pp. 43–44. ISBN 978-0-672-33370-5.
  33. 33.0 33.1 Good uses of goto, Simon Cozens
  34. 34.0 34.1 When To Use Goto When Programming in C, Alex Allain
  35. "Day 1 Keynote - Bjarne Stroustrup: C++11 Style | GoingNative 2012 | Channel 9". Channel9.msdn.com. 2012-02-02. Retrieved 2014-07-22.
  36. David Chisnall (2012). Objective-C Phrasebook. Addison-Wesley Professional. p. 249. ISBN 978-0-321-81375-6.
  37. J. Siedersleben (2006). "Errors and Exceptions - Rights and Obligations". In Christophe Dony. Advanced Topics in Exception Handling Techniques. Springer Science & Business Media. p. 277. ISBN 978-3-540-37443-5.
  38. 38.0 38.1 Guy Lewis Steele, Jr.. "Debunking the 'Expensive Procedure Call' Myth, or, Procedure Call Implementations Considered Harmful, or, Lambda: The Ultimate GOTO". MIT AI Lab. AI Lab Memo AIM-443. October 1977.
  39. R5RS Sec. 3.5, Richard Kelsey, William Clinger, Jonathan Rees et al. (August 1998). "Revised5 Report on the Algorithmic Language Scheme". Higher-Order and Symbolic Computation 11 (1): 7–105. doi:10.1023/A:1010051815785.
  40. Revised5 Report on the Algorithmic Language Scheme (R5RS), section 6.4, standard procedures: call-with-current-continuation
  41. "Computed GOTO Statement (obsolescent)". Lahey.com. Retrieved 2014-07-22.
  42. "Microsoft QuickBASIC: ON...GOSUB, ON...GOTO Statements QuickSCREEN.". Microsoft. 1988. Retrieved 2008-07-03.
  43. http://www.personal.psu.edu/jhm/f90/statements/goto_a.html
  44. "ASSIGN - Label Assignment". Software.intel.com. Retrieved 2014-07-22.
  45. Computed goto, IBM XL C/C++ compiler
  46. "Intel® Composer XE 2013 SP1 Compilers Fixes List | Intel® Developer Zone". Software.intel.com. 2013-08-12. Retrieved 2014-07-22.
  47. 47.0 47.1 "Labels as Values - Using the GNU Compiler Collection (GCC)". Gcc.gnu.org. Retrieved 2014-07-22.
  48. University of Michigan Computing Center (September 1974). MTS, Michigan Terminal System. UM Libraries. p. 226. UOM:39015034770076.
  49. HP COBOL II/XL Reference Manual, "The ALTER statement is an obsolete feature of the 1985 ANSI COBOL standard."
  50. Van Tassel, Dennie (July 8, 2004). "History of Labels in Programming Languages". Retrieved 4 January 2011.
  51. Goto, from the perl.syn (Perl syntax) manual
  52. "GOTO for Java". steike. July 6, 2009. Retrieved April 28, 2012.
  53. Sexton, Alex. "The Summer of Goto | Official Home of Goto.js". Retrieved April 28, 2012.
  54. Hindle, Richie (April 1, 2004). "goto for Python". Entrian Solutions. Hertford, UK: Entrian Solutions Ltd. Retrieved April 28, 2012. The 'goto' module was an April Fool's joke, published on 1st April 2004. Yes, it works, but it's a joke nevertheless. Please don't use it in real code!
  55. "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.
  56. "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.
  57. "goto - Manual". PHP. Retrieved 2014-07-22.