Take the 2-minute tour ×
Programmers Stack Exchange is a question and answer site for professional programmers interested in conceptual questions about software development. It's 100% free, no registration required.

Possible Duplicate:
Is it ever worthwhile using goto?

In a recent article, Andrew Koenig writes:

When asked why goto statements are harmful, most programmers will say something like "because they make programs hard to understand." Press harder, and you may well hear something like "I don't really know, but that's what I was taught." For that reason, I'd like to summarize Dijkstra's arguments.

He then shows two program fragments, one without a goto and and one with a goto:

if (n < 0)
    n = 0;

Assuming that n is a variable of a built-in numeric type, we know that after this code, n is nonnegative.

Suppose we rewrite this fragment:

if (n >= 0) goto nonneg;
n = 0;
nonneg: ;

In theory, this rewrite should have the same effect as the original. However, rewriting has changed something important: It has opened the possibility of transferring control to nonneg from anywhere else in the program.

I emphasized the part that I don't agree with. Modern languages like C++ do not allow goto to transfer control arbitrarily. Here are two examples:

  1. You cannot jump to a label that is defined in a different function.
  2. You cannot jump over a variable initialization.

Now consider composing your code of tiny functions that adhere to the single responsibility principle:

int clamp_to_zero(int n)
{
    if (n >= 0) goto n_is_not_negative:
    n = 0;
n_is_not_negative:
    return n;
}

The classic argument against the goto statement is that control could have transferred from anywhere inside your program to the label n_is_not_negative, but this simply is not (and was never) true in C++. If you try it, you will get a compiler error, because labels are scoped. The rest of the program doesn't even see the name n_is_not_negative, so it's just not possible to jump there. This is a static guarantee!

Now, I'm not saying that this version is better then the one without the goto, but to make the latter as expressive as the first one, we would at least have to insert a comment, or even better yet, an assertion:

int clamp_to_zero(int n)
{
    if (n < 0)
        n = 0;
    // n is not negative at this point
    assert(n >= 0);
    return n;    
}

Note that you basically get the assertion for free in the goto version, because the condition n >= 0 is already written in line 1, and n = 0; satisfies the condition trivially. But that's just a random observation.

It seems to me that "don't use gotos!" is one of those dogmas like "don't use multiple returns!" that stem from a time where the real problem were functions of hundreds or even thousand of lines of code.

So, do we still have a case against the goto statement, other than that it is not particularly useful? I haven't written a goto in at least a decade, but it's not like I was running away in terror whenever I encountered one. 1 Ideally, I would like to see a strong and valid argument against gotos that still holds when you adhere to established programming principles for clean code like the SRP. "You can jump anywhere" is not (and has never been) a valid argument in C++, and somehow I don't like teaching stuff that is not true.

1: Also, I have never been able to resurrect even a single velociraptor, no matter how many gotos I tried :(

share|improve this question

marked as duplicate by Yannis Rizos, ChrisF Dec 17 '11 at 22:42

This question has been asked before and already has an answer. If those answers do not fully address your question, please ask a new question.

    
    
"expressive"? What does that even mean, besides "I like it better?" –  Ebenezer Sklivvze Dec 17 '11 at 15:23
1  
@sklivvz "expressive" means "someone reading the code can see the intent easily". Yes it's subjective, but it's more meaningful than you suggest. –  slim Dec 17 '11 at 16:47
    
@slim I realise that. However, my opinion is that the presented code it's quite the opposite of expressive, and that the code without the goto it's perfectly clear. So, while I agree that expressive means something, I also think it's completely abused of, in this case. –  Ebenezer Sklivvze Dec 17 '11 at 17:50
    
@sklivvz I agree with you on that. –  slim Dec 17 '11 at 17:54

10 Answers 10

Goto's are not the problem. They never were. The problem is programmers who use goto's in such a way that it makes code extremely difficult to follow, and possibly places code into an indeterminate state (remember, not every language will be as strict as C++ is). Goto's are just the gun - but the programmer is the one who points it at his foot and pulls the trigger.

In the past I've used goto's on occasions where I concluded it was the best course of action (or, more usually, the least risky course). There's nothing wrong with doing that so long as you are aware of the possible consequences. But new coders dont necessarily have that sense and can make a major mess of things. So I suspect its far simpler to just teach them never to use gotos.

share|improve this answer
1  
In that case, I would prefer not mentioning gotos at all. –  FredOverflow Dec 17 '11 at 9:21
7  
@FredOverflow: or you can give them the advice "only use goto when you know what you're doing", which boils down to "don't" in 99% of the cases. And that's exactly what's being done nowadays: we say "don't", thereby missing that small fraction of cases where goto could be used responsibly. This is helping both the people who can and cannot foresee the implications of using goto. –  Egon Dec 17 '11 at 11:58
4  
It is always a very bad idea to teach someone "The Only Right Way". It is ok for a cult or a religion, but not for anything as rational as science or craft. Coders taught this way are blindfolded and later they'll find it really hard to be open-minded about techniques that falls out of the scope of their weird religious beliefs. So please, do not teach anyone to "never do" something. –  SK-logic Dec 17 '11 at 14:18
1  
@SK-logic, I don't fully agree. Learners at different levels need different kinds of instructions. Beginners need one clear way of doing things; explanations like "you should usually do A, but sometimes you need B, and under these and these circumstances C may also need to be considered etc." just confuse them instead of teaching them anything useful. Later, at an intermediate stage those rules can be revisited and elaborated. But only when they already firmly understand and know the "normal" way of doing things. –  Péter Török Dec 17 '11 at 23:49
2  
@Péter Török, why do you think all the beginners are idiots? Even 5 years old normal kids are capable of a very elaborate analysis. But it is easy to turn them into obedient, boxed-thinking morons if you keep teaching them "one clear way of doing things". Learners must be confused, because confusion resolution is the only way to a proper understanding. –  SK-logic Dec 18 '11 at 14:31

Ideally, I would like to see a strong and valid argument against gotos that still holds when you adhere to established programming principles for clean code

goto can be used instead of an if, a switch, for, while, break, return, and many, many other features of the language that all serve different purposes. But there's a reason languages have acquired so many branching and looping constructs: The make it easier to grasp what the code does. Using goto gives up this important feature and leaves you with Assembler-like code to decipher.

A goto is therefore inferior to all those structured language constructs.

I have been following this goto debate for almost two decades now, and in C++ I have yet to see a piece of code that could be made easier to understand by applying a goto, which wouldn't become even easier to understand by applying RAII, introducing additional (inlined) functions, or using one of the above mentioned constructs. (It's different for C, which has no RAII.)

share|improve this answer
    
Commenters: Do not continue the bickering back and forth in comments. If you have a better answer or you want to improve your answer, please do so on the question this one duplicates. If you want to have a constructive conversation about the topic of this post, please do it in chat. –  user8 Dec 19 '11 at 9:33

IMHO

if (n < 0)
  n = 0;

makes it perfectly clear that after that, n >= 0, so a comment explaining this would violate the DRY principle, and an assertion I would consider downright silly or confusing: could the author have faced some strange compiler/optimization bug at this point???

I consider the variant using goto harder to understand than plain if. This of course may simply be the effect of not being used to seeing gotos in code; but then again, most of my (current and future) coworkers aren't either, so they probably feel the same. Thus even if I got used to goto, it would make the code harder to maintain in the long run.

It seems to me that "don't use gotos!" is one of those dogmas like "don't use multiple returns!" that stem from a time where the real problem were functions of hundreds or even thousand of lines of code.

All of the legacy programs I have seen so far contain many, many functions of hundreds (or sometimes even thousands) of lines of code. So I am very happy that at least they don't contain gotos :-) You are right that in a small, clean method goto can't make a big problem; however, if you try to draw a fuzzy line like "you can use goto in functions shorter than n lines", it is inevitably going to be abused by "clever" developers. Not to mention that functions tend to grow over time; what do you do when your originally short and clean function bloats to double its size? Do you remove the gotos then, or refactor? Will your successor a few years down the line remove the gotos, or refactor the code too?... OTOH Dijkstra's rule is clear, and has much less potential to be abused.

Last but not least, your function's name does not express its intent; renaming it to e.g. make_non_negative would leave no doubt about what it does.

YMMV.

share|improve this answer

There is nothing wrong with using goto correctly. For example:

for(int i = 0; i <= 10; ++i)
{
   for(int j = 0; j <= 10; ++j)
   {
      // ..
      if(condition)
        goto end;
      // ..
   }
}

end:

The problem is using goto in a way that makes no sense such as in your example:

if (n >= 0) goto nonneg;
n = 0;
nonneg: ;

I've never ever seen this in real code (and I've seen a lot of nasty stuff) so I don't know what's all the fuss and the hate about.

Using goto that way is equivalent to:

for(int i = 0; n < 0 && i < 1; ++i)
    n = -5;

instead of

if(n < 0)
    n = -5;

This doesn't mean that for is bad, just like goto isn't.

share|improve this answer
    
+1 for use of goto as a 'named break,' which is basically the only legitimate use I've seen for it in real life (at least in a world where we have exceptions). –  fluffy Dec 17 '11 at 21:06
    
Some languages allow you to use a label together with break. It is however not a well documented thing in e.g. Java break [labelname] –  Spoike Jun 1 '12 at 11:38

Your examples are not very convincing. There are many other cases when goto is much better than any other option.

One is implementing virtual machines with the computed goto extension in GCC (see OCaml bytecode interpreter for example).

Another (very broad) case is code generation. For example, it is much more efficient (and much easier to comprehend as well) to generate a Packrat parser code from higher level, declarative PEG, using goto to escape from the failing parsing branches. If your language can be used as a target for code generation or if it is a meta language allowing to implement new language features, goto is a must have.

And a third case - state automatons. Here, goto is a natural representation of a concept of moving from one state to another, and therefore a goto-based implementation is much more readable than anything else.

But, unfortunately, many programmers were taught to a nearly religious hate and fear of the goto, and for this reason none of the above arguments are convincing enough for this lot.

share|improve this answer
    
Now, implementing VM's is hardly a day-to-day job. // With code generation, no programmer is writing the goto (I'm of the opinion that generated code can follow different rules than "normal" code). // And the last bit about state automatons -- do you have any examples? –  Martin Ba Dec 17 '11 at 19:39
1  
@Martin, all the brainwashed goto haters are proposing to kick it off from all the languages they're using. Which means they won't be able to implement a VM properly even when they'd need it. And they won't be able to generate code in their languages too, because they've removed such a useful statement. As for the examples, look at the ADVENT code here: www-cs-staff.stanford.edu/~uno/programs.html –  SK-logic Dec 18 '11 at 14:40
    
this question is tagged [C++] and the example you link to is not C++, as far as I am able to tell. Note that I do not "hate goto", as you seem to think of people that think it can and probably should be avoided in most C++ code. I am - purely out of curiosity - genuinely interested in a clean C++ code example that does it's job better that a corresponding version without goto. –  Martin Ba Dec 19 '11 at 9:23
    
@Martin, mind naming any of the idiomatic C++ features that could have been used here? There is no way C++ could improve the readability of such a basic and trivial thing, so a pure C example is good enough. If you want a nice and clean C++ example - download LLVM source code and grep for goto, you'd be surprised (and most of the cases there are FSMs). –  SK-logic Dec 19 '11 at 9:34
    
@SK-logic: this is the most balanced statement on goto I have seen in a long time, among all the other crap flying around. Since goto is the fundamental construct from which other statements are derived, why deprive the programmer of it's power for the occational need as you outlined. I have personally been in several situations where judicious use of goto whipped the pants off of case, while, if, break, function, throw, finally, etc... (notably in FSMs). This discussion is like "since you can buy everything premade at Walmart, get rid of all of the real hardware stores." –  gahooa Jan 17 '12 at 14:14

Then we must consider the great man's arguments. See a transcription of his original paper for references.

My first remark is that, although the programmer’s activity ends when he has constructed a correct program, the process taking place under control of his program is the true subject matter of his activity, for it is this process that has to effectuate the desired effect, it is this process that in its dynamic behaviour has to satisfy the desired specifications. Yet, once the program has been made, the “making” of the corresponding process is delegated to the machine.

So it is the run-time that is all-important.

My second remark is that our intellectual powers are rather geared to master static relations and that our powers to visualize processes evolving in time are relatively poorly developed. For that reason we should do (as wise programmers aware of our limitations) our utmost best to shorten the conceptual gap between the static program and the dynamic process, to make the correspondence between the program (spread out in text space) and the process (spread out in time) as trivial as possible.

(my emphasis)

More specifically, our aim is to ensure that our conceptual image of the running program matches the actual as far as possible.

And finally

... The unbridled use of the go to statement has as an immediate consequence that it becomes terribly hard to find a meaningful set of coordinates in which to describe the process progress. ...

In my opinion nothing has changed, and n'or will it ever change. goto does make it harder to describe the process progress. And since it has also been proved that any algorithm making use of goto can be rewritten to not use it, my case rests.

Just because you can use goto in a less harmful way that doesn't violate too many rules doesn't mean you should use goto. Dijkstra was right, and still is, you must maximise the simplicity of your code. Simple enough is not acceptable.

share|improve this answer
2  
A state automaton implemented with goto is much simpler than any other, more "structured" implementation. Just as another great man, D. E. Knuth, brilliantly displayed with his adventure game. –  SK-logic Dec 17 '11 at 14:24
2  
The state machine is by its very nature predictable to a higher degree than most other code. This is not what Dijkstra was talking about. A Turing machine would be even more predictable, is that therefore the best way to code all algorithms? –  OldCurmudgeon Dec 17 '11 at 17:41
    
I did not get your argument - do you mean that state machines are not easy to comprehend and should not be coded directly at all?!? –  SK-logic Dec 18 '11 at 14:41
    
I am saying state machines are a special case as they are almost totally data driven. I believe Dijkstra is discussing algorithms of a more general nature here. I am interested in Knuth's adventure game. Can you provide a link? –  OldCurmudgeon Dec 18 '11 at 16:18
    
www-cs-staff.stanford.edu/~uno/programs.html - see ADVENT there. –  SK-logic Dec 18 '11 at 16:26

It has already been said that things such as if and while and for are merely fancy gotos (albeit well-structured and understandable).

But the interesting thing is that many gotos appear where we'd ideally use something like return. @Krelp's answer is a good example:

... start of big function
for(int i = 0; i <= 10; ++i)
{
   for(int j = 0; j <= 10; ++j)
   {
      // ..
      if(condition)
        goto end;
      // ..
   }
}    
end:
... rest of big function

On the very rare occasion I've used goto (temporarily) it where I would have liked to use lightweight nested functions. It would be nice to be able to put these for loops inside a nested function and replace the goto with a return.

void big_function() {
    ... start of big function
    // next few lines declare a nested function
    void nested_function() { // shall be permitted access to the locals in the parent function
        for(int i = 0; i <= 10; ++i)
        {
           for(int j = 0; j <= 10; ++j)
           {
              // ..
              if(condition)
                return;
              // ..
           }
        }    
    }
    nested_function(); // actually call it
    ... rest of big function
}

I'd really like to see this sort of thing in C and C++, maybe lambdas will allow it. In fact, maybe global functions should be deprecated and everything should be seen as a lambda! (PS: Don't some C compilers already allow something like this?)

share|improve this answer
    
D allows nested functions like that :) –  ratchet freak Dec 17 '11 at 15:21
    
"maybe lambdas will allow it" => They already do, as of August 2011. The current standard of C++ is C++1x. Also all mainstream compilers (gcc, visual studio, etc) already support lambdas. –  Andreas Bonini Dec 17 '11 at 17:04
1  
GNU C (but neither GNU C++ nor GNU Objective C) allows nested functions. Your example code would actually compile and work as expected with GCC. But I would recommend against using this extension. –  Mackie Messer Dec 17 '11 at 17:33
    
Everything seen as a lambda? Nice idea, but I don't think C++ is ever going to do this as good as Haskell, which doesn't need to fight with an overall language design that was originally meant to be used in a completely different way. –  leftaroundabout Dec 18 '11 at 11:42

Your example is only true in trivial functions, where I can see the whole thing at once. In longer functions, it's not so trivial.

The if statement guarantees no control freakouts within the scope of one statement. I only need to comprehend that one statement to know that nothing funny happens. The goto statement guarantees no control freakouts within the scope of one function. Therefore, it's inherent that goto is harder to read than if.

share|improve this answer
    
But long functions are always hard to understand, even without a single goto. –  FredOverflow Dec 17 '11 at 14:40
    
@FredOverflow, not always. There are exceptions from this rule too. Just as with nearly any other rule. An already mentioned state automaton or a virtual machine is quite an example. –  SK-logic Dec 17 '11 at 15:02
    
Of course, with exceptions, you can never be sure what will happen inside if anyway. –  quant_dev Dec 17 '11 at 15:15
    
@FredOverflow: That's no excuse to make it even worse. –  DeadMG Dec 19 '11 at 0:36

I am using coding guidelines which allow goto (in Pascal: GOTO exit;) to drop out of a procedure or function in case of some serious error, or when no further processing is possible for whatever reason. Just to jump to the end of a routine, clean up some of the mess (free memory, unlock resources) and then exit. In fact, when including a procedure or function template in the source to code a new routine, the label 'exit' is declared per default.

About the multiple returns: I am in favour of using a local variable to assign the return value to. This can be done on multiple locations. At the end of the function, only one return is required. Together with goto, this can make code more readable, because not so many nested IF statements are required to get to the end of the routine.

However, there will always be people that tell you not to use it, but those are in most cases the ones that do not need to maintain the code.

share|improve this answer

There is simple reason why goto's are unnecessary. It's because line numbers are not available any longer. The original reason to add goto statement to basic programming language was the line numbers. The problem was that the line numbers were fixed, and you couldn't change the numbers. Goto was needed when you run out of available line numbers. Fill in all lines from 1-10, and adding new line inside that range required replacing line 7 with goto statement to line 330, moving the old line 7 to line 330, then writing some code to 331-380, and then adding goto from 380 to line 8. Now if you have thousands of blocks like this, the program will look somewhat awful and difficult to follow.

share|improve this answer
1  
JFYI, goto is much older than Basic. Imagine a machine code without branching instruction. Imagine Fortran without a goto statement. –  SK-logic Dec 17 '11 at 14:25
1  
It's not true that goto's are unnecessary. This is a very broad statement without foundation. –  Andreas Bonini Dec 17 '11 at 17:01
1  
@Krelp, maybe in assembly you need goto. In high level languages like C++ or C#, you don't. I've not used goto a single time in the over 10 years I've been programming professionally. I've never encountered a time when it would have been easier or clearer than any alternative. –  Andy Dec 17 '11 at 21:38
    
Machine code / assemblers have still the same problem with line numbers. It's just memory addresses, and inserting code in middle of existing code just doesn't work without relocating all the code after it. –  tp1 Dec 17 '11 at 23:54
    
@Andy: see programmers.stackexchange.com/a/125738/112 for examples of uses where goto is good, along with mine and many others –  Andreas Bonini Dec 18 '11 at 0:10

Not the answer you're looking for? Browse other questions tagged or ask your own question.