I don't understand why goto's are so bad. I LOVE to use it in an if-else or switch to quit a loop. But everyone says they are bad and I should not use them but no one says why! Can you explain it to me?

Software reasons:
- It reduces code readability.
- It produces inefficient code.
- It makes code maintenance harder
- ...probably many more.

Hardware reasons:
- It is inefficient.
- Branch statement are one of the most inefficient operations, and using many of those makes the hardware work more, when it might not be necessary to use them.

Ethical reasons:
- Have some heart. It is evil to use it
- You might not 'goto' heaven, if you use it.
Miscellaneous reasons:
- A dinosaur will pop out of you computer and eat you if you do.
- Your computer will kill it self
- I will kill you
- You will be condem to goto 'bad programmer's' hell.
- A dinosaur will pop out of your tv and eat you.

Ahh, I am changing all my goto's in a forever loops to good loops! I hope it isn't too late!

Mainly because of an observation by Edsger Dijkstra in 1968, where he argued "GOTO Statement Considered Harmful" (Google it and you'll find copies of the white paper)

In brief, the observation is that (In general), the number of 'goto' statements a programmer uses in their code is inversely proportional to the overall quality of that code (i.e. the code is generally less bug-ridden, easier to read, easier to maintain, etc).

the 'goto' statement, like many other features, is open to abuse; although in general (i.e. 99.99% of cases), there's simply no need for it, because the kind of 'jump' operations which programmers usually want to do can easily be encapsulated in a simple high-level flow control statement, such as if/else, for, while, switch, break, etc.

Plenty of "old" code still exists where programmers have used 'goto', and one of its problems when someone comes to maintain it, is that often a programmer will simply chuck in a harmless modification, but maybe will want to modify the flow a little too - one of the real problems with 'goto' is that changing the flow of a block which jumps around is actually very hard to do, unless you simply add in another 'goto'. the result is usually that code which started out relatively simple with only a couple of 'goto' jumps starts getting increasingly harder to follow, and turns into "spaghetti" code where nobody really knows what its doing, or why, or whether its behaviour is even correct in all cases.


If you don't believe me, here's an example which I mocked up to illustrate. This is not a "contrived" example, I really have worked with code very very similar to this (albeit in another language, not C++). Tell me if you think its easy to understand.. or better, decide for yourself what you would do if you were given the job of changing the way the insurance cost is calculated with another bit of criteria :-)

void calculate_car_insurance()
{
    double cost = 1000.0;
    int your_age, years_driving, wifes_age;

ask_age:
    std::cout << "Your age:";
    std::cin >> your_age;
    if (your_age < 17 || your_age > 65)
        goto end3;
    else if (your_age < 0 || your_age > 100)
        goto ask_age;

ask_wifes_age:
    std::cout << "Wifes age: ";
    std::cin >> wifes_age;
    if (wifes_age < 17 || wifes_age > 60)
        goto end2;
    else if (wifes_age < 0 || your_age > 100)
        goto ask_wifes_age;

ask_years_driving:
    std::cout << "Years driving: ";
    std::cin >> years_driving;
    if (years_driving < 5)
        goto end1;
    else if (years_driving < 0 || years_driving > (your_age - 17))
        goto ask_years_driving;

    if (years_driving > 10)
    {
        cost = cost / 2;
        goto end4;
    }

    if (years_driving > 15)
    {
        cost = cost / 3;
        goto end4;
    }

end1:
    std::cout << "We won't insure you to drive because you haven't been driving long enough" << std::endl;
    goto end5;
end2:
    std::cout << "We won't insure you to drive because of your wife's age" << std::endl;
    goto end5;
end3:
    std::cout << "We won't insure you to drive because of your age" << std::endl;
    goto end5;
end4:
    std::cout << "Your insurance cost: " << cost << std::endl;
end5:
    std::cout << "goodbye." << std::endl;
}

>>A dinosaur will pop out of your computer and eat you if you do.

I wish it could be required by the C++ standard to devour any programmer who writes a "goto" statement.


>>I don't understand why goto's are so bad.

A goto statement is a relic from the times when most programmers where used to programming assembly code (which relies, of course, on labels and jumps (i.e. gotos)). There are many programming paradigms (functional prog., procedural prog., object-oriented prog., imperative prog., declarative prog., generic prog., meta-prog., etc. etc.), by far the worse of them all is "spaghetti coding", and that is what gotos are "useful" for. All other paradigms are based on some sort of logic, "spaghetti code" is not. For example, in procedural prog. ("C-style"), a program is basically a sequence of state transitions (like a FSM), the state is all the variables of the program and the transitions are the functions. The logic behind it is that each function should require some pre-conditions (the state of its inputs), and produce a predictable post-condition (outputs). Then, the act of coding in procedural programming is all about putting the right sequence together (and branches, of course). Most other (high-level) paradigms are built on top of this fundamental logic. The goto statement is an explicit violation of this procedural prog. logic by jumping discontinuously across the sequence of transitions. It is, in itself, a maintainability nightmare. Any trivial use of a goto-statement can easily be replaced by a loop and/or break/continue mechanism or function calls. And any non-trivial use of a goto-statement is unmaintainable and sometimes very dangerous.

A goto can be dangerous because it does not respect scope, does not pay any attention to the stack-frame's integrity, and can easily lead to unpredictable behaviour. I have programmed for about 12 years, and I have never used a goto statement and I don't know anyone who would. In fact, I was shocked to find out that C/C++ still supported a goto-statement (at that time, I had already many years of experience, so I didn't have to even think for a second as to why goto-statements are absolute evil!).

Programmers determine when it is good or when it is bad to use goto . It is not goto that determines whether programmer is good or bad. It is perfectly fine to use goto if you can maintain the readability of your code. Since most of goto 's job has been replaced by control statement, that's why we can rarely see goto being used. However, it still has its own place where it is necessary to use goto because alternative solutions (using control statement) fails.

However, it still has its own place where it is necessary to use goto because alternative solutions (using control statement) fails.

'fails' is not really the right word IMO. For every conceivable programming problem you can think of, there is always more than one way to solve it; and code which uses goto is no exception since it can always be refactored to use alternative flow control (functions, if/else, loops, etc). The question is one of time/cost effectiveness.

Usually its something like this: You have some code which works just the way you want it to work, except there is one minor caveat which needs a tweak in order to handle a particular case. It may be that reworking the flow to handle this causes ripples throughout your code and your design, and has a potential negative effect on other behaviour. That doesn't mean the other flow control itself has "failed", it means that there's a design issue, and reworking it will need additional design, implementation and testing effort beyond the simple case that you want to handle in order to devise a good solution.
- If dropping a 'goto' in to the code is the quick-easy-solution, chances are that its the "best" solution on the basis that the risk of introducing unwanted side-effects, or coming up against other constraints outweighs the ugly/undesirable factor of using a dirty hack.

However, if the existing code never had 'goto' in there in the first place, chances are that the minor modification will not need 'goto' either. :)

- If dropping a 'goto' in to the code is the quick-easy-solution, chances are that its the "best" solution on the basis that the risk of introducing unwanted side-effects, or coming up against other constraints outweighs the ugly/undesirable factor of using a dirty hack.

Is adding "goto" always introducing more unwanted side-effects than regular control statement? Is control statement always improve readability?

There are more than mere "goto" alone or "control statement" alone that contribute in code readability and maintainability. In some cases, "goto" produces even more readable code than "control statement" does.

I have heard that Knuth actually designed an algorithm that required a GOTO. It could not be removed using flow control. I don't know more than that, but I believe it was created in response to the "GOTO's are bad and unnecessary" movement -- just to be ornery.

Is adding "goto" always introducing more unwanted side-effects than regular control statement? Is control statement always improve readability?

If there were any rules like this where you could use the word "always", then problems would be simple :)

There are more than mere "goto" alone or "control statement" alone that contribute in code readability and maintainability. In some cases, "goto" produces even more readable code than "control statement" does.

You've missed my point though, which is that sometimes while updating existing code you can spend days rewriting something which didn't need to change, and in-turn require your QA/Tester to spend days re-testing functionality which shouldn't have changed, through a desire to write well-formed code, when all you needed was a quick, dirty, ugly hack which took 5 minutes to code/test and gets the job done.


Just to clarify - i'm playing devil's advocate a little bit. i.e. Readability, maintainability, and all the other sacred cows which exist for the good of us all usually go out of the window when there's a tight deadline and the real-world factors start to bite. And these are the times when ugly hacks aren't so bad. Otherwise, if you've got all the time/resource in the world then you can write the most elegant and well-designed solution you like :)

I have heard that Knuth actually designed an algorithm that required a GOTO. It could not be removed using flow control. I don't know more than that, but I believe it was created in response to the "GOTO's are bad and unnecessary" movement -- just to be ornery.

Well, I have heard that Chuck Norris actually designed an algorithm that required nothing

I have heard that Knuth actually designed an algorithm that required a GOTO.

Unless you can provide a citation, I'm skeptical.

Unless you can provide a citation, I'm skeptical.

Fine by me. As I said, "I have heard", not "he did"

What is true is that in his paper Structured Programming with goto Statements, Knuth gave an example of a clever programming technique for removing a boolean variable from a program by duplicating the relevant portions of the program and jumping back and forth between then with goto statements. And it is also true that it is possible to write code that uses goto statements that cannot easily be rewritten without them unless you introduce additional variables. But there's a theorem that says that any program that uses goto statements can be rewritten without them as long as you're willing to duplicate code or introduce additional variables; which is why I'm skeptical.

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.