Become a MacRumors Supporter for $50/year with no ads, ability to filter front page stories, and private forums.
Please get rid of the goto. Use break instead. GOTO is useful in assembly code, but in a language like C, it just continues a practice that will lead to spaghetti code. Nip it in the bud, and you'll be thankful later.

But comeon! With GOTO you can eliminate loops!

Code:
//graciously ripped from php.net
StartOfLoop:
$i++;
if($i < 1000000) goto StartOfLoop;
 
I would sacrifice readability to efficiency. Which of the four code snippets that mydogisbox posted is the most efficient on average?
 
I would sacrifice readability to efficiency. Which of the four code snippets that mydogisbox posted is the most efficient on average?

You should almost never sacrifice readability for efficiency. Efficiency gives you one thing: speed. Readability gives you less bugs, easier to maintain code, code that is easier for others to understand, and code that is easier for you yourself to understand when you revisit it. Considering a program spends the vast majority of its execution time on a considerably small subset of the code, you should always focus on readability, then, and only if the code doesn't meet performance requirements, you should modify critical sections as needed for performance. Realize also that compilers are relatively smart these days. When you make an optimization, you always need to performance test it to be sure that it's actually making things faster.
 
Wirelessly posted (Mozilla/5.0 (iPhone; U; CPU iPhone OS 4_2_1 like Mac OS X; en-us) AppleWebKit/533.17.9 (KHTML, like Gecko) Version/5.0.2 Mobile/8C148 Safari/6533.18.5)

I could see scenarios where the single loop version that substitutes arithmetic for conditionals and jumps might actually outperform any of the nested loop versions.

For all you know after optimization you could end up with totally different code.

B
 
I would sacrifice readability to efficiency. Which of the four code snippets that mydogisbox posted is the most efficient on average?

An optimizing compiler may well produce identical results for logically identical semantics, either coded with structured statements, or with lots of gotos.

In these cases (logically identical code and a smart enough compiler), there is no efficiency advantage to not using goto statements. With a dumber compiler, you might get it to produce tighter looking code using gotos, but the branch predictor inside a heavily pipelined superscaler (p4, i5, i7, etc.) CPU might render this efficiency moot.

The advantage of using structured code is that a typo is more likely to be spotted by the compiler's static analyzer as an error.

Whichever is more readable is a matter of training. Current schools produce programmers untrained in reading gotos. If you work with old-time programmers, the opposite may be true.
 
Wirelessly posted (Mozilla/5.0 (iPhone; U; CPU iPhone OS 4_2_1 like Mac OS X; en-us) AppleWebKit/533.17.9 (KHTML, like Gecko) Version/5.0.2 Mobile/8C148 Safari/6533.18.5)

I could see scenarios where the single loop version that substitutes arithmetic for conditionals and jumps might actually outperform any of the nested loop versions.

For all you know after optimization you could end up with totally different code.

B

It most certainly would be faster: branching is expensive. Then again, in some cases the compiler might actually do this automatically.
 
Last edited:
I can't remember the last time I used a continue, break, or goto statement (the only exception being the required breaks in case statements). There is almost always another and/or better way.

firewood is right about optimizing compilers. They will likely reduce gotos and structured statements to similar assembly code.
 
An optimizing compiler may well produce identical results for logically identical semantics . . .

Are you saying that a smart compiler will interpret the following code as if the variable "found" did not exist?

Code:
bool found = false;
for(int i = 0; i<10 && !found; i++){
    for(int j = 0; j<10 && !found;j++){
        for(int k = 0; k<10 && !found;k++){
            if(condition == true /* peudo-code*/) found = true;
        }
    }
}
 
Are you saying that a smart compiler will interpret the following code as if the variable "found" did not exist?

Code:
bool found = false;
for(int i = 0; i<10 && !found; i++){
    for(int j = 0; j<10 && !found;j++){
        for(int k = 0; k<10 && !found;k++){
            if(condition == true /* peudo-code*/) found = true;
        }
    }
}

Are you having a performance problem in an area of code that looks like this? If not, this isn't the right time to be worrying about that sort of nuance. Premature optimization is your enemy. Until your program works completely correctly and you've pinpointed that a chunk of code is performing poorly, spend your time and energy on robustness, correctness, and readability.

If this is academic interest, compile using -S in gcc with the optimization set where you want it.

-Lee
 
Are you saying that a smart compiler will interpret the following code as if the variable "found" did not exist?

Depends on the static analyzer, but yes an smart optimizer might notice the sequence of redundant test and branch instructions and collapse the branch chain into a much simpler one. Just like they move redundant computations out of inner loops, and throw away dead code if possible.
 
Code:
bool found = false;
for(int i = 0; i<10 && !found; i++)
{
  for(int j = 0; j<10 && !found;j++)
  {
    for(int k = 0; k<10 && !found;k++)
    {
      if(condition == true /* peudo-code*/)found = true;
    }
  }
}

Why do you find the goto cleaner?
B

I think the goto is cleaner because the flow of the program is more apparent. Having the "&& !found" mixed into the for statements mixes the looping through the data structure with stopping early when the desired item is found.

In my mind, those are two separate actions, and putting them on the same line just makes it less readable. When thinking about these things I try to think in terms of conceptual chunks and mixing the "loop through the structure" chunk with the "I've found what I want" chunk makes it harder for me to understand. Plus, it just feels convoluted to me.

While the "while" is pretty from an "ooo, cool!" standpoint, it also doesn't clearly separate out the different things that are happening in the loop.

Someone else also suggested using nested functions. I might be inclined to go with this method depending on the circumstance, but with a simple "find an item in the data structure" loop I would still go with the hated "goto", because, again, the functions would break up the conceptual flow of the program.

Edit:
Making program flow more apparent is the exact same reason I will, most of the time, argue strongly against using a goto statement. Having 5 goto statements cris-crossing all over the place in a function makes the flow impossible to follow.
 
Last edited:
Having 5 goto statements cris-crossing all over the place in a function makes the flow impossible to follow.

Straying from common design patterns is what makes a program hard to follow.

With some effort, most 5 criss-crossing spaghetti code gotos could probably be converted into a logically equivalent mess of mixed for/if/switch/while/do statements and boolean flag variables that would be just as hard to follow.
 
I think the goto is cleaner because the flow of the program is more apparent.

In general I don't think that burying the exit condition in the middle of the loop makes anything more apparent. At first glance, I would expect your preferred loop/goto version to access and test all 1000 data points.

As Sydde's points out using goto in this way precludes you from converting bits of the code to functions because the goto crosses {} boundaries. If the body of your loop grows and you want to parse it out as a function you'll need to change it.

Note that the while loop is also a more "OOP"y way of looking at the problem. I have a collection of stuff to look through, I don't really care that it is accessed via three separate indices, just that I want to find something within that collection of data.

B
 
That actually isn't true (assuming he changes his "if (numerator == 0)" to "if (denominator == 0)"). To my understanding, mod 0 is undefined and thus he would need to break before trying to calculate the remainder if he wants to have a program that won't crash.
Right. I guess I was thinking about a while-loop that says, "while (denominator != 0)". Someone suggested such a loop instead of a do-while loop.
 
There is one case where goto is very useful: resource cleanup!

Code:
foo = malloc(wada wada ....)
if(foo == NULL) return /* whatever */;

omg = malloc(another wada wada...);
if(omg == NULL)
    goto omg_ml_fail;

bananas= malloc(last wada promise);
if(banana == NULL)
    goto banana_ml_fail;

...
free(banana);

banana_ml_fail:
free(omg);

omg_ml_fail:
free(foo);
 
There is one case where goto is very useful: resource cleanup!
hmmm, you will have to provide a better example than that
Code:
foo = malloc(wada wada ....)
if ( foo != NULL ) {
    omg = malloc(another wada wada...);
    if ( omg != NULL ) {
        ...
        bananas= malloc(last wada promise);
        if ( banana != NULL ) {
            ...
            free(banana);
        }
        free(omg);
        ...
    }
    free(foo);
}
// IMO, using goto labels as an alternative for comments fails to make sense
// but indented code between the { ... } improves readability
 
I'm wondering whether the avoidance is really on the level of superstition.

It's almost always superstition. People hear that 'goto' is terrible, and propagate that without understanding why 'goto' is dangerous. But it's actually appropriate sometimes. I very rarely use gotos, but sometimes they really are the best alternative in plain C. (I've never needed a goto in C++.) I think Knuth says it best, in the comments in the advent.w file:

By the way, if you don't like goto statements, don't read this. (And don't read any other programs that simulate multistate systems.)
 
hmmm, you will have to provide a better example than that
Code:
foo = malloc(wada wada ....)
if ( foo != NULL ) {
    omg = malloc(another wada wada...);
    if ( omg != NULL ) {
        ...
        bananas= malloc(last wada promise);
        if ( banana != NULL ) {
            ...
            free(banana);
        }
        free(omg);
        ...
    }
    free(foo);
}
// IMO, using goto labels as an alternative for comments fails to make sense
// but indented code between the { ... } improves readability
I haven't seen anything like this in any programming language where the computer manages storage automatically. No explicit malloc, no explicit freeing, no pointers left dangling when you free the storage they point to.

Sure, automatic memory management requires overhead. But Eiffel programs manage their own memory. If you know it's safe to do it, you can tell the machine not to generate code to collect garbage with.
 
It's almost always superstition. People hear that 'goto' is terrible, and propagate that without understanding why 'goto' is dangerous. But it's actually appropriate sometimes. I very rarely use gotos, but sometimes they really are the best alternative in plain C. (I've never needed a goto in C++.) I think Knuth says it best, in the comments in the advent.w file:

I don't know. I guess i need to see some counter-examples of the use of goto being terrible. Yes, i've heard it's terrible. And i've seen the horrors it brings. Maybe some people can use it "responsibly", but I have never seen some code using gotos and said "yep, goto is the way to go. That makes perfect sense". Maybe i have only read code written by fools, but anecdotally I have read a lot of code and never has code using gotos been clearer than code using other control structures.

I know others can provide anecdotal evidence to the contrary, that they have seen pristine, readable code that only uses gotos. I'm simply providing this because you stated that it's almost always superstition. I'm stating that I have seen concrete evidence that it can be terrible, so I have strong reasons for saying people should avoid it. You did say "almost always", but I don't know that my experience is a rare exception.

-Lee
 
Last edited:
It's almost always superstition.

Not at all. In my case, the first two languages I worked with (in school) were HP 2000 BASIC and Burroughs E4000. In BASIC, the only flow control structure that was not a form of goto was for/next (not to mention it was all numbered lines). After learning to use a nice cleanly structured language like C, the very thought of using using a goto makes my gorge rise.
 
As with many things superstition often arises from experience. (To paraphrase what lee1210 and Sydde said.)

In BASIC, the only flow control structure that was not a form of goto was for/next (not to mention it was all numbered lines).
BASIC remained my primary programming language from 1978-1992 or so and I spent a lot of time over that time dealing with communally written spaghetti code even after BASIC lost line numbers and gained other control structures. (Along the way I also learned FORTRAN, Pascal, Modula-2 and some C but BASIC was the core language used.).

B
 
I don't know. I guess i need to see some counter-examples of the use of goto being terrible. Yes, i've heard it's terrible. And i've seen the horrors it brings. Maybe some people can use it "responsibly", but I have never seen some code using gotos and said "yep, goto is the way to go. That makes perfect sense". Maybe i have only read code written by fools, but anecdotally I have read a lot of code and never has code using gotos been clearer than code using other control structures.

I know others can provide anecdotal evidence to the contrary, that they have seen pristine, readable code that only uses gotos. I'm simply providing this because you stated that it's almost always superstition. I'm stating that I have seen concrete evidence that it can be terrible, so I have strong reasons for saying people should avoid it. You did say "almost always", but I don't know that my experience is a rare exception.

-Lee

To be clear, I think gotos should be avoided in most situations. In particular, if a programmer doesn't really understand why gotos are problematic, then he shouldn't be using them at all. I've only used them in production code (in front-end of a compiler) a handful of times, mostly for error handling (to conform with existing conventions).

On the other hand, Knuth uses gotos much more liberally than I do (http://www-cs-faculty.stanford.edu/~knuth/programs/advent.w.gz), and he's a far better programmer than I'll ever be.
 
Not at all. In my case, the first two languages I worked with (in school) were HP 2000 BASIC and Burroughs E4000. In BASIC, the only flow control structure that was not a form of goto was for/next (not to mention it was all numbered lines). After learning to use a nice cleanly structured language like C, the very thought of using using a goto makes my gorge rise.

You say it's not superstition, but you don't mention a reason for avoiding gotos!
 
Last edited:
You say it's not superstition, but you don't mention a reason for avoiding gotos!

It's only 4 pages:
http://www.cs.utexas.edu/users/EWD/ewd02xx/EWD215.PDF

Other than the points Dijkstra presents, in practical usage in reading code written in procedural languages go to can completely obliterate your reasoning about the flow of a program. At any point execution might jump to any label. You were in a loop, now you aren't. You were counting coins in a jar, you made it to $1.30, now you're shearing a sheep. What happened?

Surely if go to was the only control structure available those of us that chose to still bother with programming would be more familiar with reading it, and would simply adjust our expectations about program flow.

As for the source file that's been posted by Knuth... all I can say is he was unfortunate enough to be converting from FORTRAN (all caps means a version prior to 77, which the comments mention is the year the code was completed). By far the worst code I've read has been fortran old enough to be referred to as FORTRAN.

-Lee
 
Register on MacRumors! This sidebar will go away, and you'll see fewer ads.