goto... is it so bad?

64 views
Skip to first unread message

Sushrut Sardeshmukh

unread,
Mar 26, 2007, 3:51:56 AM3/26/07
to
I recently found goto used in a tiny part of (very large C / C++ mix)
code base.
I realized that I have never seen goto before (except college time).
I was so hammered about so called bad effect of goto that I never used
it myself. Nor I thought if it is really so bad. (Since I have never
really seen / used goto, I have not faced any bad effects of it)

I threw this question into my work place group. Only one argument came
up. And it said 'it makes code unreadable'

1. Is it really so bad to use goto? Does any one supports / use it?
2. If goto is so bad, then why C++ still supports it? May be to
maintain compatibility with 'C'. In that case, compiler should give
out a warning, right?
3. For every place where goto was used, there were better ways to plan
the code in the code base I discussed above. But ......is there any
situation where goto is must?


Note: I work for an Investment bank. So I am not into writing stuff
like kernel and device drivers.


--
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]

James Kanze

unread,
Mar 26, 2007, 5:53:27 AM3/26/07
to
On Mar 26, 9:51 am, "Sushrut Sardeshmukh" <bestbr...@gmail.com> wrote:
> I recently found goto used in a tiny part of (very large C / C++ mix)
> code base.
> I realized that I have never seen goto before (except college time).
> I was so hammered about so called bad effect of goto that I never used
> it myself. Nor I thought if it is really so bad. (Since I have never
> really seen / used goto, I have not faced any bad effects of it)

> I threw this question into my work place group. Only one argument came
> up. And it said 'it makes code unreadable'

> 1. Is it really so bad to use goto? Does any one supports / use it?

It's not so much the goto in itself that causes the problem.
It's the where you're coming from, at the label. In practice,
deviating from any of the standard structures does make code
unreadable, very, very quickly, and C++ has direct support for
all of the standard structures, so there's never any need for
it.

> 2. If goto is so bad, then why C++ still supports it? May be to
> maintain compatibility with 'C'. In that case, compiler should give
> out a warning, right?

History. And it's not the sort of thing you're likely to do
accidentally, without meaning to, so it's not really worth the
compiler writers' effort to generate the warning.

> 3. For every place where goto was used, there were better ways to plan
> the code in the code base I discussed above. But ......is there any
> situation where goto is must?

I think that's the key. In well written code, I don't think
that there is ever a need. On the other hand, perhaps in some
critical situations, where the profiler says you must...
(Typically, the optimizer should be able to do just as well, if
not better, with normal coding structures. But if it doesn't,
you sometimes have to hack it.)

Still, I've been writing software in C or C++ for something like
25 years now, much of it time critical, and I've never needed a
goto.

--
James Kanze (GABI Software) email:james...@gmail.com
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34

Carl Barron

unread,
Mar 26, 2007, 5:52:48 AM3/26/07
to
In article <1174891072.7...@n76g2000hsh.googlegroups.com>,
Sushrut Sardeshmukh <best...@gmail.com> wrote:

> I recently found goto used in a tiny part of (very large C / C++ mix)
> code base.
> I realized that I have never seen goto before (except college time).
> I was so hammered about so called bad effect of goto that I never used
> it myself. Nor I thought if it is really so bad. (Since I have never
> really seen / used goto, I have not faced any bad effects of it)
>
> I threw this question into my work place group. Only one argument came
> up. And it said 'it makes code unreadable'
>
> 1. Is it really so bad to use goto? Does any one supports / use it?

In the 1960's it was proven that with structured loops [for loops,
while loops, do while loops, and structured if statements such as C or
C++ has the need for goto is eliminated, Use of goto is prone to
produce unreadable and unmaintainable code and is to be avoided chiefly
because of this.

> 2. If goto is so bad, then why C++ still supports it? May be to
> maintain compatibility with 'C'. In that case, compiler should give
> out a warning, right?

Compilers don't give warnings for using 'ancient' but supported
techniques,

> 3. For every place where goto was used, there were better ways to plan
> the code in the code base I discussed above. But ......is there any
> situation where goto is must?

I see no real need for goto's in most application code.

Tony Delroy

unread,
Mar 26, 2007, 8:45:40 AM3/26/07
to
> [ are gotos really evil ]...

Some examples of times it may be cleaner to use goto:

- in C++, if you have nested for or while loops, you can't break out
of
multiple loops easily. It may be both faster and more maintainable
to
use a goto.
- in case statements, you sometimes have multiple cases that need
trivial
initial processing, but then do the same processing as some other
label.
If you don't want to factor the common code out to a function, or
there
are reasons not to (like convenient access to local variables), then
you may prefer a goto
- very seldom, you have some really nicely written code then find a
strange
corner case, and you'll be tempted to handle it with a goto rather
than
rework your entire function. Probably most of the time, it's better
to
rework, but perhaps not always.
- there are some famous optimisations for efficient data copying that
rely on gotos to jump into a contiguous set of operation code at a
position that ensures the right number of iterations are run
probably a few others I can't think of off the top of my head...

Walter Bright

unread,
Mar 26, 2007, 8:49:16 AM3/26/07
to
James Kanze wrote:
> And it's not the sort of thing you're likely to do
> accidentally, without meaning to, so it's not really worth the
> compiler writers' effort to generate the warning.

It's trivial to add a warning for using a goto. It isn't done because
there's no demand for it. Like you say, it's not like people
accidentally write semantically valid goto statements.


> I think that's the key. In well written code, I don't think
> that there is ever a need. On the other hand, perhaps in some
> critical situations, where the profiler says you must...
> (Typically, the optimizer should be able to do just as well, if
> not better, with normal coding structures. But if it doesn't,
> you sometimes have to hack it.)

The Digital Mars compilers work by transforming all coding structures
into basic blocks connected by gotos. All optimizations (including loop
invariants, loop induction variables, etc.) are done on this graph.

The algorithms for doing this are classic and well known (I was taught
them in 1982). There's no legitimate reason for a professional compiler
to do any worse with gotos than with structured code.

Walter Bright
http://www.digitalmars.com C, C++, D programming language compilers

Walter Bright

unread,
Mar 26, 2007, 8:47:55 AM3/26/07
to
Sushrut Sardeshmukh wrote:
> I recently found goto used in a tiny part of (very large C / C++ mix)
> code base.
> I realized that I have never seen goto before (except college time).
> I was so hammered about so called bad effect of goto that I never used
> it myself. Nor I thought if it is really so bad. (Since I have never
> really seen / used goto, I have not faced any bad effects of it)
>
> I threw this question into my work place group. Only one argument came
> up. And it said 'it makes code unreadable'
>
> 1. Is it really so bad to use goto?

No. It has its place when you find yourself trying to contort other
control structures that don't quite fit what you want to do.

> Does any one supports / use it?

I regularly use it, probably more than anyone else I know. If you want a
sample of it in professional code, see
http://ftp.digitalmars.com/dmd.zip and grep for goto in /dmd/src/dmd/

> 2. If goto is so bad, then why C++ still supports it?

Probably because of curmudgeons like me who keep using it <g>. Yes, D
has a goto statement, too. Note even if one has religious zeal against
gotos, for machine generated source code having it is pretty handy.

> May be to
> maintain compatibility with 'C'. In that case, compiler should give
> out a warning, right?

It's not like anyone types 'goto Label;' by accident. If you really want
to scan for them, using "grep" will do just fine. I've been called on
the carpet by QA folks several times for using goto's they found by
using grep. Fun always ensues <g>.

> 3. For every place where goto was used, there were better ways to plan
> the code in the code base I discussed above. But ......is there any
> situation where goto is must?

One place I use it is in switch statements:

switch (x)
{ case 1:
case 2:
... do some code ...
goto Ldefault;
case 3:
... do some code ...
goto Lcase_5;
case 4:
... do some code ...
Lcase_5:
case 5:
... do some code ...
break;
Ldefault:
default:
... do some code ...
break;
}

In fact, I do it often enough that "goto default" and "goto case expr"
are part of the D programming language's switch statement:

switch (x)
{ case 1:
case 2:
... do some code ...
goto default;
case 3:
... do some code ...
goto case 5;
case 4:
... do some code ...
case 5:
... do some code ...
break;
default:
... do some code ...
break;
}

Other common uses:

1) multilevel breaks.
2) combining block exit cleanup code
3) combining common error exits
4) avoiding reformatting/reorganizing a large block of code to do a
minor edit
5) machine generated source
6) state machines

etc.

Bottom line:

1) yes, it is possible to rewrite every use of goto with some
combination of other structures. Whether the result is better or worse
is up to you, the programmer.

2) if you use goto, be prepared to defend each use of it when the QA
folks or your boss asks you about it.

3) if the guy who signs your paycheck has a thing about not using gotos,
you'd be well advised to not use them <g>.

Zeljko Vrba

unread,
Mar 26, 2007, 8:49:48 AM3/26/07
to
On 2007-03-26, Sushrut Sardeshmukh <best...@gmail.com> wrote:
>
> 1. Is it really so bad to use goto? Does any one supports / use it?
>
No if you use it judiciously. I'd dare say that most people don't know
when goto would be appropriate, so they are given a religious statement
"goto is evil". D. E. Knuth wrote an article "Structured Programming with
GOTO". Here's a link:

http://pplab.snu.ac.kr/courses/adv_pl05/papers/p261-knuth.pdf

>
> 2. If goto is so bad, then why C++ still supports it? May be to
>

It makes code _clearer_ in certain situations.

>
> the code in the code base I discussed above. But ......is there any
> situation where goto is must?
>

Yes, the simplest example is to bail out of nested loops:

while(a) {
while(b) {
if(something)
goto out_a; // exit the outer loop
}
// more code
}
out_a: // rest of the program

Try to rewrite the above code without using goto. In C++ you _could_
use exceptions for that (although, it's questionable how much more
"readable" that would be), in C you don't even have exceptions.

Another example is hard-coding finite-state automata transitions within
a function.

Other examples could be thought of.

>
> Note: I work for an Investment bank. So I am not into writing stuff
> like kernel and device drivers.
>

It doesn't matter where you work. What is important is not to let
yourself be brainwashed :)

Alf P. Steinbach

unread,
Mar 26, 2007, 10:12:25 AM3/26/07
to
* Sushrut Sardeshmukh:

> I recently found goto used in a tiny part of (very large C / C++ mix)
> code base.
> I realized that I have never seen goto before (except college time).
> I was so hammered about so called bad effect of goto that I never used
> it myself. Nor I thought if it is really so bad. (Since I have never
> really seen / used goto, I have not faced any bad effects of it)
>
> I threw this question into my work place group. Only one argument came
> up. And it said 'it makes code unreadable'
>
> 1. Is it really so bad to use goto? Does any one supports / use it?

For manually written code 'goto' is in most cases better expressed by
'break', 'continue' or 'return'.

A case might be made for breaking out of a doubly or triply nested loop,
but then, a case might be made for doing that using 'return'.

On the other hand, I believe tools such 'lex' still generate
'goto'-based state machines. At least they used to.


> 2. If goto is so bad, then why C++ still supports it?

C++ supports low level programming in general.

Remove all those language features and you have a language with all the
problems associated with low level programming, and none of the advantages.


> May be to
> maintain compatibility with 'C'. In that case, compiler should give
> out a warning, right?

Why?


> 3. For every place where goto was used, there were better ways to
plan
> the code in the code base I discussed above. But ......is there any
> situation where goto is must?

No.

But then, the same can be said about any language feature.


--
A: Because it messes up the order in which people normally read text.
Q: Why is it such a bad thing?
A: Top-posting.
Q: What is the most annoying thing on usenet and in e-mail?

Francis Glassborow

unread,
Mar 26, 2007, 10:18:09 AM3/26/07
to
James Kanze wrote:
> I think that's the key. In well written code, I don't think
> that there is ever a need. On the other hand, perhaps in some
> critical situations, where the profiler says you must...
> (Typically, the optimizer should be able to do just as well, if
> not better, with normal coding structures. But if it doesn't,
> you sometimes have to hack it.)
>
> Still, I've been writing software in C or C++ for something like
> 25 years now, much of it time critical, and I've never needed a
> goto.
In much the same time span I have never had anyone offer me a convincing
example of where it solved a problem other than with poorly designed
code. In addition I have a sneaky suspicion that it causes problems with
exception safety, particularly as it has function scope rather than
block scope.

Quite apart from readability issues its use also creates maintenance ones.
Francis Glassborow

Francis Glassborow

unread,
Mar 26, 2007, 10:58:22 AM3/26/07
to
Tony Delroy wrote:
>> [ are gotos really evil ]...
>
> Some examples of times it may be cleaner to use goto:
>
> - in C++, if you have nested for or while loops, you can't break out
> of
> multiple loops easily. It may be both faster and more maintainable
> to
> use a goto.

Any speed advantage is minuscule (well it might be faster for a naive
programmer to 'design' and write the resulting code?). However, nested
loops, conditionals etc. are almost always a maintenance nightmare and I
do not see how using goto would reduce that.

> - in case statements, you sometimes have multiple cases that need
> trivial
> initial processing, but then do the same processing as some other
> label.
> If you don't want to factor the common code out to a function, or
> there
> are reasons not to (like convenient access to local variables), then
> you may prefer a goto

In 25 years of programming in C and over 15 of doing so in C++ I cannot
recall a single time when I would have wanted to do that.

> - very seldom, you have some really nicely written code then find a
> strange
> corner case, and you'll be tempted to handle it with a goto rather
> than
> rework your entire function. Probably most of the time, it's better
> to
> rework, but perhaps not always.

That is a matter of opinion, and not one I share. That temptation is
exactly why goto is such a problem.

> - there are some famous optimisations for efficient data copying that
> rely on gotos to jump into a contiguous set of operation code at a
> position that ensures the right number of iterations are run
> probably a few others I can't think of off the top of my head...
>
>

Yes, and though such things are amusing, they also have no place in
modern code.

Of course the above are my (strongly held) opinions but I would dearly
like to see a single real example. Every goto I have ever encountered
disappears when the code is redesigned to be simpler, more readable and
more maintainable.

Francis Glassborow

unread,
Mar 26, 2007, 10:59:20 AM3/26/07
to
Zeljko Vrba wrote:
> Yes, the simplest example is to bail out of nested loops:
>
> while(a) {
> while(b) {
> if(something)
> goto out_a; // exit the outer loop
> }
> // more code
> }
> out_a: // rest of the program
>
> Try to rewrite the above code without using goto. In C++ you _could_
> use exceptions for that (although, it's questionable how much more
> "readable" that would be), in C you don't even have exceptions.
>

But you are assuming that that code itself is necessary. Without knowing
more details it is hard to rewrite but given the context I would expect
to redesign the code without much trouble.

However:

while(a) {
while(b and not something){
// code which might change the
// truth value of something
}
if(something) break;
// more code
}

Now it is immediately clear that the inner loop is only executed until
either 'b' or 'not something' evaluates as false. And if you need to
micro-optimize you can write 'not something and b' if the loop normally
terminates on something becoming true.

It is also clear that the outer loop terminates when something is true.
Though I do try to avoid using break to exit a loop (unless it is the
only way out so I might actually write:

while(true){
while(b and not something){
// code which might change the
// truth value of something
}
if(something or not a) break;
// more code
}

Which also makes it clear that the outer loops termination condition is
actually that a be true and something be false.

And yes, you can keep coming up with counter examples, and I can keep
shooting them down. That is just tedious.

Walter's upthread examples are exactly what I would expect from someone
who (like me) learnt his craft with assembler. The problem caused to
maintenance is that you have to check every change at both the come from
and arrive at point.

James Hopkin

unread,
Mar 26, 2007, 11:00:16 AM3/26/07
to
On Mar 26, 3:18 pm, Francis Glassborow <franc...@robinton.demon.co.uk>
wrote:

>
> In much the same time span I have never had anyone offer me a convincing
> example of where it solved a problem other than with poorly designed
> code. In addition I have a sneaky suspicion that it causes problems with
> exception safety, particularly as it has function scope rather than
> block scope.
>

I can't think of any exception safety problems with goto. In fact, I
look at it the other way round: exception-safe code is also 'goto
safe' (and 'break/continue safe' and 'early return safe').

I don't have the combined 50 years experience of you two ;-), but FWIW
I haven't come across a genuine use for goto either. I've just used it
once or twice as the quickest way to try something out, but there's
always been a pretty obvious, much better way of writing the code.


James

Daniel T.

unread,
Mar 26, 2007, 11:00:28 AM3/26/07
to
"Sushrut Sardeshmukh" <best...@gmail.com> wrote:

> I recently found goto used in a tiny part of (very large C / C++ mix)
> code base.
> I realized that I have never seen goto before (except college time).
> I was so hammered about so called bad effect of goto that I never used
> it myself. Nor I thought if it is really so bad. (Since I have never
> really seen / used goto, I have not faced any bad effects of it)
>
> I threw this question into my work place group. Only one argument came
> up. And it said 'it makes code unreadable'

http://www.acm.org/classics/oct95/

> 1. Is it really so bad to use goto? Does any one supports / use it?

It isn't the word itself that is bad of course. If used responsibly, if
the code structure is maintained, there is nothing especially wrong with
it. "The go to statement as it stands is just too primitive; it is too
much an invitation to make a mess of one's program." (Dijkstra) Of
course if you never accept the invitation...

Stephen Howe

unread,
Mar 26, 2007, 5:18:52 PM3/26/07
to
> while(true){
> while(b and not something){
> // code which might change the
> // truth value of something
> }
> if(something or not a) break;
> // more code
> }

What if a is false to start with?
Your version will start executing the the inner while loop while the
original goto version, the outer while loop wont even start.
That 2nd set of while loops is not isomorphic to the original while loop
with goto.

> And yes, you can keep coming up with counter examples, and I can keep
> shooting them down.

Not with incorrect replacements you cant.

I dont regard those transformed while loops as clearer, in fact they look
plain ugly, worse than the original while loops with 1 goto.
If the outer loop is really controlled by a, why not express that intent
with "while (a)"?
If the inner loop is really controlled by b, why not express that intent
with "while (b)"?
You have replaced the working code with some ugly contortions, far worse
than the goto alternative.

For me, it is not "use goto" or "not use goto" that is the rule.
It is "which looks clearer?", and sometimes, particularly with deeply nested

loops, the goto version does looks clearer.
And clearer code is more maintainable.

Cheers

Stephen Howe

Edward Rosten

unread,
Mar 26, 2007, 5:18:14 PM3/26/07
to
On Mar 26, 3:53 am, "James Kanze" <james.ka...@gmail.com> wrote:
> On Mar 26, 9:51 am, "Sushrut Sardeshmukh" <bestbr...@gmail.com> wrote:

> It's not so much the goto in itself that causes the problem.

So, you're a fan of intercal? :-)

> It's the where you're coming from, at the label. In practice,
> deviating from any of the standard structures does make code
> unreadable, very, very quickly, and C++ has direct support for
> all of the standard structures,

I wouldn't have said so, exactly. Some other languages (for instance,
BASH) allow break and continue to take a number which indicates the
nesting level to operate on. Jumping out of a nested loop requires a
goto.

> so there's never any need for
> it.

I work with images, so I frequently have a loop over rows and a loop
columns (as opposed to a loop over elements in a linear container).
This means I occasionally need gotos (well, more often than 1 in 25
years, at any rate).


> > 3. For every place where goto was used, there were better ways to
plan
> > the code in the code base I discussed above. But ......is there any
> > situation where goto is must?
>
> I think that's the key. In well written code, I don't think
> that there is ever a need.

I've also found them useful in machine generated code. Machines don't
have a problem getting it right.

I've also used it for small, ad-hoc parsers. For instance, consider
parsing coordinates structured like this:
(<ws><integer><ws>,<ws><integer><ws>)
<ws> stands for optional whitespace. The following function will parse
this, and set the bad bit if the data has the incorrect structure:

istream& operator>>(Coordinate& ref)
{
unsigned char c = is.get();

if(is.eof())
return is;

if(c == '(' )
{
is >> std::ws >> ref.x >> std::ws;

if(is.get() != ',')
goto bad;

is >> std::ws >> ref.y >> std::ws;

if(is.get() != ')')
goto bad;
}

bad:
is.setstate(std::ios_base::badbit);

return is;
}


It's got gotos. Is there a much cleaner way?

-Ed

Stephen Howe

unread,
Mar 26, 2007, 5:13:23 PM3/26/07
to
> In much the same time span I have never had anyone offer me a convincing
> example of where it solved a problem other than with poorly designed code.

What about the example illustrating goto in the K & R book - multiple loops
and you need to jump out of all of them?
goto is what I use in these circumstances when there is no alternative and
return will not do.

And what is the alternative to this?
1. Artificially creating extra boolean variables to see which loops need
exiting and are checked in the loop control structures?
2. Artificially hoisting the multiple loop block code and placing it a
function, just so that you can use "return"?

The options 1 & 2 are so dreadful, so poor, that I reach for goto. 1 & 2
suffer from their own readability issues - I have to write far more lines of

code than the goto alternative. I use goto roughly once a year in code,
usually for exit & cleanup situations.

Over the years I have seen some mendbendingly strange use of control
structures written just to avoid using goto.

Stephen Howe

Vladimir Marko

unread,
Mar 26, 2007, 5:28:05 PM3/26/07
to
On 26 Mar, 13:47, Walter Bright <wal...@digitalmars-nospamm.com>
wrote:

> Sushrut Sardeshmukh wrote:
> > 1. Is it really so bad to use goto?
>
> No. It has its place when you find yourself trying to contort other
> control structures that don't quite fit what you want to do.
>
> > Does any one supports / use it?
>
> I regularly use it, probably more than anyone else I know. If you want a
> sample of it in professional code, see http://ftp.digitalmars.com/dmd.zip
> and grep for goto in /dmd/src/dmd/

That's pure C, isn't it? goto is certainly useful in C, but there are
better tools for the job in C++.

Making a quick search for goto in the whole dmd.zip I had a look into
a few
random .d files. And I'm very curious, it's not written in full D is
it?
May be a very small subset? (If it was written in full D, I would have
to
state that either D is comparable with C89 or the programmer is
incompetent
or [s]he is deliberately obfuscating the code.)

>
> > 2. If goto is so bad, then why C++ still supports it?

> > May be to
> > maintain compatibility with 'C'. In that case, compiler should give
> > out a warning, right?
>
> It's not like anyone types 'goto Label;' by accident. If you really want
> to scan for them, using "grep" will do just fine. I've been called on
> the carpet by QA folks several times for using goto's they found by
> using grep. Fun always ensues <g>.

I would easily defend many uses of goto in C code. On the other hand,
defending frequent use of goto in C++ might prove impossible.

>
> > 3. For every place where goto was used, there were better ways to
plan
> > the code in the code base I discussed above. But ......is there any
> > situation where goto is must?
>
> One place I use it is in switch statements:
>
> switch (x)

> ...
> }

A switch statement is already a nicely packaged bunch of gotos, so
adding
a few more feels quite acceptable.

> Other common uses:
>
> 1) multilevel breaks.

The last time I saw reasonable 3 nested loops was Floyd-Warshal
algorithm
many years ago. And whenever I needed to break out of 2 nested loops
it
was either by return, or I just rewrote the inner loop using find/
find_if
anyway because _I_ find it more readable.

> 2) combining block exit cleanup code

I thought that's what RAII is for in C++.

> 3) combining common error exits

Ehm, is "goto nomatch;" more readable than "return nomatch;" where
nomatch
is a local enumerator defined at the _beginning_ of the function
(where it
nicely documents the return values)?

> 4) avoiding reformatting/reorganizing a large block of code to do a
> minor edit

Minor edit today, minor edit tomorrow, total mess in a week.

> 5) machine generated source

Agreed.

> 6) state machines

May be, if performance is of utmost importance.

> Bottom line:
>
> 1) yes, it is possible to rewrite every use of goto with some
> combination of other structures. Whether the result is better or worse
> is up to you, the programmer.

Of course. However, the effort required to make the code with gotos
readable is usually much higher than with other tools available in C+
+.

Regards
Vladimir Marko

Daniel Krügler

unread,
Mar 26, 2007, 5:20:34 PM3/26/07
to

James Hopkin schrieb:

> I don't have the combined 50 years experience of you two ;-), but FWIW
> I haven't come across a genuine use for goto either. I've just used it
> once or twice as the quickest way to try something out, but there's
> always been a pretty obvious, much better way of writing the code.

<confession>
(Slightly redfaced): Interestingly I can remember that I used
goto once, but it was not in a C or C++ program but instead
in a Pascal program, where the code computed a hash value.
I searched in my old sources and here we go(to):

case Len of
11: goto Pos11;
10: goto Pos10;
9: goto Pos09;
8: goto Pos08;
7: goto Pos07;
6: goto Pos06;
5: goto Pos05;
4: goto Pos04;
3: goto Pos03;
2: goto Pos02;
1: goto Pos01;
else goto Pos00;
end;

Pos11: c := c + (UInt32(Key[10]) shl 24);
Pos10: c := c + (UInt32(Key[9]) shl 16);
Pos09: c := c + (UInt32(Key[8]) shl 8);
// The first byte of c is reserved for the length:
Pos08: b := b + (UInt32(Key[7]) shl 24);
Pos07: b := b + (UInt32(Key[6]) shl 16);
Pos06: b := b + (UInt32(Key[5]) shl 8);
Pos05: b := b + UInt32(Key[4]);
Pos04: a := a + (UInt32(Key[3]) shl 24);
Pos03: a := a + (UInt32(Key[2]) shl 16);
Pos02: a := a + (UInt32(Key[1]) shl 8);
Pos01: a := a + UInt32(Key[0]);
Pos00: // case 0: nothing left to add

As you see, this code effectively simulated
a C switch statement ;-)
</confession>

Greetings from Bremen,

Daniel Kr|gler

Walter Bright

unread,
Mar 26, 2007, 5:21:55 PM3/26/07
to
Francis Glassborow wrote:
> It is also clear that the outer loop terminates when something is true.
> Though I do try to avoid using break to exit a loop (unless it is the
> only way out so I might actually write:
>
> while(true){
> while(b and not something){
> // code which might change the
> // truth value of something
> }
> if(something or not a) break;
> // more code
> }
>
> Which also makes it clear that the outer loops termination condition is
> actually that a be true and something be false.

Whether that is clearer or not is a personal matter of style and
opinion. To me, this example is less clear than the goto version. One
reason I use gotos is to avoid code duplication and duplicate testing of
conditionals (the "something" in your example). I find duplication to be
a maintenance problem because I have to a) visually check to ensure they
really are duplicates and b) remember that when I change one, I must
change the other in sync. Even worse, the need to move "something" out
of the inner loop may require declaring more variables and moving
declarations of variables out of inner scopes, and spreading the
initialization/use of such variables across larger swaths of code. For
example:

while(a) {
while(b) {
if(foo())


goto out_a; // exit the outer loop
}
// more code
}
out_a: // rest of the program

becomes:

while(true){
bool tmp = false;
while(b && !(tmp = (foo() != 0))){


// code which might change the
// truth value of something
}

if(tmp or not a) break;
// more code
}

I have to look at that pretty carefully to see if it really is the same
as the simple goto version.

> And yes, you can keep coming up with counter examples, and I can keep
> shooting them down. That is just tedious.

I think we can all agree that since it's been proven that one can always
be transformed into the other, it is pointless to produce counter
examples showing that it can be done.

> Walter's upthread examples are exactly what I would expect from someone
> who (like me) learnt his craft with assembler.

Basic, FORTRAN, and assembler, all of which relied on goto <g>.

> The problem caused to
> maintenance is that you have to check every change at both the come from
> and arrive at point.

As opposed to checking the duplication of code (even if the optimizer
can get rid of the duplication, the maintenance programmer still has to
see it, check it, etc.)

I don't use goto gratuitously - if a structured statement will fit, I'll
use that instead. If it doesn't, I won't. I try not to use a crowbar as
a hammer, either, even if it can drive nails <g>. I might also add that
I use fewer goto's in D programming because D has a richer panopoly of
structured statements that obviate many uses of gotos, such as
multilevel breaks (useful in the above example) and scope guards.

Kaba

unread,
Mar 26, 2007, 5:26:47 PM3/26/07
to
> 1. Is it really so bad to use goto? Does any one supports / use it?

Aside the readability issues, here's a more severe one. This one is from
the C++ reference book "C++ in a nutshell". Page 93: (talking about the
goto statement)

"Jumping into a block is usually a bad idea. In particular, if the jump
bypasses the declaration of an object, the results are undefined unless
the object has POD type and no initializer."

Now imagine generic code combined with goto's and someone changing a
type from a native to a user-defined type. Then again, you don't even
need genericity to be able to imagine similar situations.

--
Kalle Rutanen
http://kaba.hilvi.org

Niels Aan de Brugh

unread,
Mar 26, 2007, 5:29:05 PM3/26/07
to
Sushrut Sardeshmukh wrote:

> 1. =C2=A0 =C2=A0 =C2=A0Is it really so bad to use goto? Does any one su=
pports / use it?

No, I never really had to, but I wouldn't avoid it per se. I regularly se=
e
people using continue, break (in loops) and multiple returns, and that's
almost as messy as a goto. So there's no real reason for goto to be such =
a
pariah among keywords.

> 2. =C2=A0 =C2=A0 =C2=A0If goto is so bad, then why C++ still supports i=


t? May be to
> maintain compatibility with 'C'. In that case, compiler should give
> out a warning, right?

As others have pointed out, goto is part of C++ so why the warning? Warni=
ngs
should be about possible unwanted/unforeseen behavior, not coding style (=
we
have tools like TICS for that).

You might be interested in this:

http://kerneltrap.org/node/553/2131

Although I don't agree with Linus' rather harsh opinion about Wirth and
(especially) Dijkstra the articles do bring up a few valid points.

N.

Walter Bright

unread,
Mar 26, 2007, 6:13:43 PM3/26/07
to
Vladimir Marko wrote:
> On 26 Mar, 13:47, Walter Bright <wal...@digitalmars-nospamm.com>
> wrote:
>> I regularly use it, probably more than anyone else I know. If you want a
>> sample of it in professional code, see http://ftp.digitalmars.com/dmd.zip
>> and grep for goto in /dmd/src/dmd/
>
> That's pure C, isn't it? goto is certainly useful in C, but there are
> better tools for the job in C++.

It's C++. The front end is in C++ to make it easier to connect with
existing back ends, which are likely to be in C or C++.


>> 2) combining block exit cleanup code
> I thought that's what RAII is for in C++.

Yes, you can do it with RAII, but creating classes for the sole purpose
of manipulating control flow (rather than storing state) is a
contortion, not clarification.

My favorite solution for this is actually the scope guard statement:
http://www.digitalmars.com/d/exception-safe.html
invented by Andrei Alexandrescu and Petru Marginean


>> 3) combining common error exits
>
> Ehm, is "goto nomatch;" more readable than "return nomatch;" where
> nomatch
> is a local enumerator defined at the _beginning_ of the function
> (where it
> nicely documents the return values)?

6 of one, half dozen of the other.

red floyd

unread,
Mar 26, 2007, 10:59:10 PM3/26/07
to
Stephen Howe wrote:
>> In much the same time span I have never had anyone offer me a convincing
>> example of where it solved a problem other than with poorly designed code.
>
> What about the example illustrating goto in the K & R book - multiple loops
> and you need to jump out of all of them?
> goto is what I use in these circumstances when there is no alternative and
> return will not do.
>
> And what is the alternative to this?
> 1. Artificially creating extra boolean variables to see which loops need
> exiting and are checked in the loop control structures?
> 2. Artificially hoisting the multiple loop block code and placing it a
> function, just so that you can use "return"?

In C++, you have the option of throwing an exception as well. In C, I
agree that

for (...)
{
for (...)
{
if (some condition)
goto disaster;
}
}
disaster:
loop end code...

isn't bad.

red floyd

unread,
Mar 26, 2007, 10:59:30 PM3/26/07
to
Kaba wrote:

>
> "Jumping into a block is usually a bad idea. In particular, if the jump
> bypasses the declaration of an object, the results are undefined unless
> the object has POD type and no initializer."
>


In C99, goto into a block is illegal. ISO/IEC 9899:1999 6.8.6.1/1

In C++, jumping into a block is legal : ISO/IEC 14882:2003 6.7/3, but
the quoted restriction applies.

--

Kirit Sælensminde

unread,
Mar 26, 2007, 11:08:11 PM3/26/07
to
On Mar 27, 4:18 am, "Edward Rosten" <Edward.Ros...@gmail.com> wrote:
> I've also used it for small, ad-hoc parsers. For instance, consider
> parsing coordinates structured like this:
> (<ws><integer><ws>,<ws><integer><ws>)
> <ws> stands for optional whitespace. The following function will parse
> this, and set the bad bit if the data has the incorrect structure:
>
> istream& operator>>(Coordinate& ref)
> {
> unsigned char c = is.get();
>
> if(is.eof())
> return is;
>
> if(c == '(' )
> {
> is >> std::ws >> ref.x >> std::ws;
>
> if(is.get() != ',')
> goto bad;
>
> is >> std::ws >> ref.y >> std::ws;
>
> if(is.get() != ')')
> goto bad;
> }
>
> bad:
> is.setstate(std::ios_base::badbit);
>
> return is;
>
> }

Do you really mean to set badbit on 'is' after successfully parsing?
It seems to me that your use of goto has introduced a bug.

How about this?

istream& operator>>(Coordinate& ref)
{
unsigned char c = is.get();

if(is.eof())
return is;

if(c == '(' )
{
is >> std::ws >> ref.x >> std::ws;

if(is.get() != ',') {


is.setstate(std::ios_base::badbit);
return is;
}

is >> std::ws >> ref.y >> std::ws;

if(is.get() != ')')
is.setstate(std::ios_base::badbit);

} else is.setstate(std::ios_base::badbit);

return is;

}

NB - Not been through a compiler.

This version doesn't do the same thing though. If the parse is
successful then it doesn't set badbit. I don't think that the return
after the first check is really needed as setting badbit will be
remembered and the rest of the parse attempts can be left to silently
re-fail.

In terms of properly usable code though this also leaves something to
be desired. It will leave the Coordinate partially initialised on a
syntax error and it doesn't report what the error is. Personally I'd
prefer to use exceptions for this sort of error.


K

Joe Gottman

unread,
Mar 26, 2007, 11:09:56 PM3/26/07
to
Edward Rosten wrote:

> I wouldn't have said so, exactly. Some other languages (for instance,
> BASH) allow break and continue to take a number which indicates the
> nesting level to operate on. Jumping out of a nested loop requires a
> goto.

I dislike that construct. It can be tedious to count how deep you
are in a series of nested loops, and if someone adds or removes a layer
your program's behavior silently changes. I much prefer Perl's idiom of
named loops.

Joe Gottman

Howard Hinnant

unread,
Mar 26, 2007, 11:08:24 PM3/26/07
to
I'm not terribly fond of me-too posts. But I kept trying to contribute
to this one and, dang it, Walter kept repeatedly expressing my own
thoughts better than I could. :-)

In article <9umdnX_yMN5qj5Xb...@comcast.com>,
Walter Bright <wal...@digitalmars-nospamm.com> wrote:

> I don't use goto gratuitously - if a structured statement will fit, I'll
> use that instead. If it doesn't, I won't. I try not to use a crowbar as
> a hammer, either, even if it can drive nails <g>. I might also add that
> I use fewer goto's in D programming because D has a richer panopoly of
> structured statements that obviate many uses of gotos, such as
> multilevel breaks (useful in the above example) and scope guards.

-Howard

Carl Barron

unread,
Mar 26, 2007, 11:06:40 PM3/26/07
to
In article <1174931686.9...@l75g2000hse.googlegroups.com>,
Edward Rosten <Edward...@gmail.com> wrote:

>
> I've also found them useful in machine generated code. Machines don't
> have a problem getting it right.
>
> I've also used it for small, ad-hoc parsers. For instance, consider
> parsing coordinates structured like this:
> (<ws><integer><ws>,<ws><integer><ws>)
> <ws> stands for optional whitespace. The following function will parse
> this, and set the bad bit if the data has the incorrect structure:
>

why badbit since the usual meaning of failbit includes syntax error of
the textual representation of the expected type? using failbit makes
it simpler just to set the failbit when the chars read are wrong, the
system will handle the ints, and stop inputting if the failbit of the
stream is set.

> istream& operator>>(istream &is,Coordinate& ref)
> {
char c;
if(is >> c && c!='(') is.setstate(std::ios_base::failbit);
is >> ref.x)
if(is >> c && c!=',') is.setstate(std::ios_base::failbit);
is >> ref.y;
if(is >> c && c!=')') is.setstate(std::ios_base::failbit);
return is;
}

looks cleaner to me and is definitely shorter.

Kirit Sælensminde

unread,
Mar 26, 2007, 11:09:29 PM3/26/07
to
On Mar 26, 2:51 pm, "Sushrut Sardeshmukh" <bestbr...@gmail.com> wrote:
> I realized that I have never seen goto before (except college time).
> I was so hammered about so called bad effect of goto that I never used
> it myself. Nor I thought if it is really so bad. (Since I have never
> really seen / used goto, I have not faced any bad effects of it)

To really understand the horror of goto you need to look at how older
languages dealt with control flow. Early BASIC for example. As you
probably don't have access to a BASIC interpreter you can simulate the
same sort of thing in C++ by following these simple rules (these are
off the top of my head):

* Every line must have a numbered label. Numbers must not be out of
order.
* Each line may have only a single statement.
* You may use functions, but you may not pass any arguments. All
variables must be global.
* You may not use braces except when using a for loop. for loops may
be nested.
* for loops may only have numeric counters.
* No while or do loops.
* You may use std::vector, std::string, int and float. std::vectors
may nest, i.e. you can have arrays of arrays.

This leads to things like this:

int main() {
L10: std::out << "Hello world" << std::endl;
L20: goto L10;
}

A simple if statement looks like this:

L50: if ( somecondition ) goto L100;
L60: // else part
L90: goto L150;
L100: // somecondition part
L150: // post if statement code

Now image that your program has a few hundred lines. Now imagine one
that has a few thousand.


K

Anand Hariharan

unread,
Mar 26, 2007, 11:06:02 PM3/26/07
to
On Mar 26, 2:51 am, "Sushrut Sardeshmukh" <bestbr...@gmail.com> wrote:
(...)
> 1. Is it really so bad to use goto? Does any one supports / use it?
> 2. If goto is so bad, then why C++ still supports it? May be to

> maintain compatibility with 'C'. In that case, compiler should give
> out a warning, right?
> 3. For every place where goto was used, there were better ways to plan
> the code in the code base I discussed above. But ......is there any
> situation where goto is must?
>

If your project is entirely in C, use of goto is unavoidable IMHO.
One would typically find code like so:

void Func(void)
{
/* Declare all your pointers at the very top, and initialise to NULL
right at beginning */

/* Initialise Return Code to Failure */

/* Keep checking for return codes of every function you call. Persist
with other checks (e.g., invariants). If something fails, set Func's
return code and jump to "CleanUp_Label" */


/* Set Return Code to Success */
CleanUp_Label:

/* For each pointer that represents a resource, if pointer not NULL,
release resource corresponding to pointer */

}

Trying to avoid goto just because it is religious is not fruitful. Of
course, in C++, one has exceptions and RAII, so the need for goto is
far less.

- Anand

Howard Hinnant

unread,
Mar 26, 2007, 11:08:24 PM3/26/07
to
I'm not terribly fond of me-too posts. But I kept trying to contribute
to this one and, dang it, Walter kept repeatedly expressing my own
thoughts better than I could. :-)

> I don't use goto gratuitously - if a structured statement will fit, I'll
> use that instead. If it doesn't, I won't. I try not to use a crowbar as
> a hammer, either, even if it can drive nails <g>. I might also add that
> I use fewer goto's in D programming because D has a richer panopoly of
> structured statements that obviate many uses of gotos, such as
> multilevel breaks (useful in the above example) and scope guards.

-Howard

Phlip

unread,
Mar 27, 2007, 3:24:57 AM3/27/07
to
Sushrut Sardeshmukh wrote:

> 1. Is it really so bad to use goto? Does any one supports / use it?

'goto' is a "design smell". It is a hint that your design probably has
other
faults, and you should follow your nose to find what they are.

> 2. If goto is so bad, then why C++ still supports it?

Because a language you can't abuse is a language you can't entirely use.

Language designers are not nannies, who think they must hold our hands
as we
learn to walk. The languages that slavishly enforce their designers' pet
principles are typically the worst ones in the world.

> 3. For every place where goto was used, there were better ways to
> plan
> the code in the code base I discussed above. But ......is there any
> situation where goto is must?

Suppose you notice a goto. If it actually damages your ability to read or
refactor a function, then that design smell might lead you to notice the
function is way too long. If the function is short, the label must be near
the goto, so it would be less of a problem.

That leads to the ideal that the goto could be replaced by a block
structure - an if or a do-while.

Good code might still use 'goto' to exit from a nested loop. And this
represents code that could refactor into an even better function, and use
'return' to exit the nested loop.

You probably saw code without unit tests. (Look them up - they are
super-important.) Without tests, as soon as a stretch of code works, you
typically resist changing its design. So if a 'goto' made the final cut,
the
risk of removing it may seem higher than the benefit of more readable
code -
especially if you can't make its function shorter or put its loops into
functions. Because you don't have unit tests to help rapidly detect if your
change was safe.

> Note: I work for an Investment bank. So I am not into writing stuff
> like kernel and device drivers.

Then you should be using a soft language (softer than Java, for example)
that gives lots of room for unit tests, and advanced structures (such as
block-closures) that give even fewer excuses to use 'goto'. Or even the
design smells that are more subtle and harder to spot!

(Under the burden of occassionally making you >cough< throw execptions for
normal control-flow...)

--
Phlip
http://flea.sourceforge.net/PiglegToo_1.html

Edward Rosten

unread,
Mar 27, 2007, 3:22:22 AM3/27/07
to
On Mar 26, 9:08 pm, "Kirit Sælensminde" <kirit.saelensmi...@gmail.com>
wrote:

> Do you really mean to set badbit on 'is' after successfully parsing?
> It seems to me that your use of goto has introduced a bug.

The copy/paste bug. I cut off a chunk of the parser which deals with
other cases, and deleted a "return is" by mistake.

> In terms of properly usable code though this also leaves something to
> be desired. It will leave the Coordinate partially initialised on a
> syntax error and it doesn't report what the error is. Personally I'd
> prefer to use exceptions for this sort of error.

Now consider a more complicated case, where the coordinate is never
left in a partially initialized state. In my version, that code would
all go in the bit after "bad:". Without the goto, this would be
duplicated.

Perhaps I should have included the full version which will accept (a,
b) [a b] or just a b, and cleans up properly.

I think made it too brief to make my point.

-Ed

Gerhard Menzl

unread,
Mar 27, 2007, 6:53:11 AM3/27/07
to
Walter Bright wrote:

> Yes, you can do it with RAII, but creating classes for the sole
> purpose of manipulating control flow (rather than storing state) is a
> contortion, not clarification.

An interesting point of view. Do you also consider replacing
switch(type) constructs by class hierarchies as a contortion?

--
Gerhard Menzl

Non-spammers may respond to my email address, which is composed of my
full name, separated by a dot, followed by at, followed by "fwz",
followed by a dot, followed by "aero".

James Kanze

unread,
Mar 27, 2007, 6:53:01 AM3/27/07
to
On Mar 26, 2:49 pm, Walter Bright <wal...@digitalmars-nospamm.com>
wrote:
> James Kanze wrote:
> > And it's not the sort of thing you're likely to do
> > accidentally, without meaning to, so it's not really worth the
> > compiler writers' effort to generate the warning.

> It's trivial to add a warning for using a goto. It isn't done because
> there's no demand for it. Like you say, it's not like people
> accidentally write semantically valid goto statements.

Exactly. I've never seen a goto which "accidentally" crept in.
(Come to think of it, I don't think I've ever seen a goto in any
of the C or C++ code I've read, except in some machine generated
code.)

> > I think that's the key. In well written code, I don't think

> > that there is ever a need. On the other hand, perhaps in some
> > critical situations, where the profiler says you must...
> > (Typically, the optimizer should be able to do just as well, if
> > not better, with normal coding structures. But if it doesn't,
> > you sometimes have to hack it.)

> The Digital Mars compilers work by transforming all coding structures
> into basic blocks connected by gotos. All optimizations (including loop
> invariants, loop induction variables, etc.) are done on this graph.

> The algorithms for doing this are classic and well known (I was taught
> them in 1982). There's no legitimate reason for a professional compiler
> to do any worse with gotos than with structured code.

That is, I believe, the usual process. I do know of at least
one compiler (for Modula-2), however, that based itself on the
explicitly written structures, and didn't even try to optimize
if there was a goto. According to the authors of the compiler,
this resulted in much faster optimization, at no cost to typical
(Modula-2) programs.

Of course, most of the optimizing technology that you would have
been taught in 1982 was developed for Fortran, where you didn't
have that luxury. One could argue that, today, we could do
better. Still, it's a tried and true technology, and if I were
writing a compiler today, I'd probably use it, not because I
want to support goto particularly well, but because I know it
works, given the number of compilers which use it.

--
James Kanze (GABI Software) mailto:james...@gmail.com
Conseils en informatique orient?e objet/
Beratung in objektorientierter Datenverarbeitung
9 place S?mard, 78210 St.-Cyr-l'?cole, France, +33 (0)1 30 23 00 34


--

James Kanze

unread,
Mar 27, 2007, 6:53:05 AM3/27/07
to
On Mar 26, 11:18 pm, "Edward Rosten" <Edward.Ros...@gmail.com> wrote:
> On Mar 26, 3:53 am, "James Kanze" <james.ka...@gmail.com> wrote:

> > It's the where you're coming from, at the label. In practice,
> > deviating from any of the standard structures does make code
> > unreadable, very, very quickly, and C++ has direct support for
> > all of the standard structures,

> I wouldn't have said so, exactly. Some other languages (for instance,
> BASH) allow break and continue to take a number which indicates the
> nesting level to operate on. Jumping out of a nested loop requires a
> goto.

Which is a sure recepe for unreadable, and especially for
fragile programs. (In fact, I never use break in C++, except to
end a case in a switch.)

> > so there's never any need for
> > it.

> I work with images, so I frequently have a loop over rows and a loop
> columns (as opposed to a loop over elements in a linear container).
> This means I occasionally need gotos (well, more often than 1 in 25
> years, at any rate).

I can see that being a case where you might actually have nested
loops (as opposed to putting the inner loop in another
function), but I still don't see why terminating a nested loop
is any different than terminating a single loop. (But as I
said, I don't use break even with a single loop.)

> > > 3. For every place where goto was used, there were better ways to plan
> > > the code in the code base I discussed above. But ......is there any
> > > situation where goto is must?

> > I think that's the key. In well written code, I don't think
> > that there is ever a need.

> I've also found them useful in machine generated code. Machines don't
> have a problem getting it right.

I can agree there. There's no necessity for machine generated
code to be "well written". Not only does the machine have no
problem getting it right in the first place, no one has to read
and understand the code it generates either.

> I've also used it for small, ad-hoc parsers. For instance, consider
> parsing coordinates structured like this:
> (<ws><integer><ws>,<ws><integer><ws>)
> <ws> stands for optional whitespace. The following function will parse
> this, and set the bad bit if the data has the incorrect structure:

> istream& operator>>(Coordinate& ref)
> {
> unsigned char c = is.get();
> if(is.eof())
> return is;

Attention: this is a dangerous error. You don't read a value,
but you don't position anything to tell the caller that you
haven't read it.

> if(c == '(' )
> {
> is >> std::ws >> ref.x >> std::ws;
>
> if(is.get() != ',')
> goto bad;
>
> is >> std::ws >> ref.y >> std::ws;
>
> if(is.get() != ')')
> goto bad;
> }
>
> bad:
> is.setstate(std::ios_base::badbit);
>
> return is;
>
> }

> It's got gotos. Is there a much cleaner way?

How about:

class match
{
public:
match( char ch ) : c( ch ) {}
friend istream& operator>>( istream& source, match const& m )
{
if ( source ) {
char ch ;
source >> ch ;
if ( ch != m.c ) {
source.setstate( ios::failbit ) ;
}
}
return source ;
}
private:
char c ;
} ;

istream& operator>>( istream& in, Coordinate& ref )
{
return in >> match( '(' ) >> ref.x
>> match( ',' ) >> ref.y >> match( ')' ) ;
}

It's not transactional. (It may modify ref even if there is an
error.) But neither is yours. It also obeys the standard
conventions for istream (using failbit for formatting errors).
And of course, match is generally usable; if you regularly use
istream to read formatted data, you probably already have it
anyway.

In production code, of course, I'd aim for a transactional
behavior, so the body of the >> operator would look more like:

double x, y ;
if ( in >> match( '(' ) >> x >> match( ',' ) >> y >>
match( ')' ) ) {
ref.x = x ;
ref.y = y ;
}
return in ;

Still no goto:-).

--
James Kanze (GABI Software) mailto:james...@gmail.com
Conseils en informatique orient?e objet/
Beratung in objektorientierter Datenverarbeitung
9 place S?mard, 78210 St.-Cyr-l'?cole, France, +33 (0)1 30 23 00 34

James Kanze

unread,
Mar 27, 2007, 6:53:05 AM3/27/07
to
On Mar 27, 9:22 am, "Edward Rosten" <Edward.Ros...@gmail.com> wrote:

> Perhaps I should have included the full version which will accept (a,
> b) [a b] or just a b, and cleans up properly.

istream&
operator>>( istream& in, ref& out )
{
double x, y ;
in >> ws ;
switch ( in.peek() ) {
case EOF :
in.setstate( ios::failbit ) ;
break ;

case '[' :
in >> match( '[' ) >> x >> y >> match( ']' ) ;
break ;

case '(' :


in >> match( '(' ) >> x >> match( ',' ) >> y >>

match( ')' ) ;
break ;

default :
in >> x >> y ;
break ;
}
if ( in ) {


ref.x = x ;
ref.y = y ;
}
return in ;
}

Still no goto, and I've handled the complete case in about as
many lines as you used for the simplified version.

--
James Kanze (GABI Software) mailto:james...@gmail.com
Conseils en informatique orient?e objet/
Beratung in objektorientierter Datenverarbeitung
9 place S?mard, 78210 St.-Cyr-l'?cole, France, +33 (0)1 30 23 00 34

Francis Glassborow

unread,
Mar 27, 2007, 10:04:55 AM3/27/07
to
{ Quoted signature removed. -mod }

Anand Hariharan wrote:
> Trying to avoid goto just because it is religious is not fruitful.

I would agree.


Of
> course, in C++, one has exceptions and RAII, so the need for goto is
> far less.

However I have never needed to use a goto in C. I am not saying that
goto is useless, just that it has very limited use and when used by a
non-expert it is almost invariably an indicator of poor coding.

It becomes useful in machine generated code exactly because writing
generators that can do design on the fly is a rather hard task :) And as
the code will not be maintained by humans (well not usually) the
problems with readability and maintenance are non-issues.

Daniel T.

unread,
Mar 27, 2007, 10:08:36 AM3/27/07
to
"Edward Rosten" <Edward...@gmail.com> wrote:
> "Kirit Sælensminde" <kirit.saelensmi...@gmail.com> wrote:
>
> > Do you really mean to set badbit on 'is' after successfully parsing?
> > It seems to me that your use of goto has introduced a bug.
>
> The copy/paste bug. I cut off a chunk of the parser which deals with
> other cases, and deleted a "return is" by mistake.

Interestingly enough, this is exactly the kind of problem that Dijkstra
warns about in his paper. You lost one of your textual indexes.

Kirit Sælensminde

unread,
Mar 27, 2007, 12:43:03 PM3/27/07
to
On Mar 27, 5:53 pm, "James Kanze" <james.ka...@gmail.com> wrote:
> switch ( in.peek() ) {
> case EOF :
> in.setstate( ios::failbit ) ;
> break ;
>
> case '[' :
> in >> match( '[' ) >> x >> y >> match( ']' ) ;
> break ;
>
> case '(' :
> in >> match( '(' ) >> x >> match( ',' ) >> y >>
> match( ')' ) ;
> break ;
>
> default :
> in >> x >> y ;
> break ;
> }

Without getting into the whole "is a switch statement really just a
glorified goto", does it not suffer one of the problems of goto, that
being bypassing constructors?

switch ( 1 ) {
std::string str;
case 1: str = "ouch";
}

My impression is that this will bypass the constructor. Am I wrong? (I
really hope that I am).

I did find out somewhere else (I think via Reddit) that Microsoft make
use of goto within MFC. It was always a pretty horrid framework from a
C++ point of view, but I'm sure there's a fair bit of buggy code out
there caused by this sort of issue.


K

Andrei Alexandrescu (See Website For Email)

unread,
Mar 27, 2007, 2:58:10 PM3/27/07
to
James Kanze wrote:
[snip]

> In production code, of course, I'd aim for a transactional
> behavior, so the body of the >> operator would look more like:
>
> double x, y ;
> if ( in >> match( '(' ) >> x >> match( ',' ) >> y >>
> match( ')' ) ) {
> ref.x = x ;
> ref.y = y ;
> }
> return in ;
>
> Still no goto:-).

Well, for my money, using iostreams already puts the code in a low
quality bracket :o).

Andrei

Pete Becker

unread,
Mar 27, 2007, 3:02:38 PM3/27/07
to
Kirit Sælensminde wrote:
>
> Without getting into the whole "is a switch statement really just a
> glorified goto", does it not suffer one of the problems of goto, that
> being bypassing constructors?
>
> switch ( 1 ) {
> std::string str;
> case 1: str = "ouch";
> }
>
> My impression is that this will bypass the constructor. Am I wrong? (I
> really hope that I am).
>

No, you're right. But you're missing the point. goto is bad, switch is
good. So when goto does bad things, that proves you shouldn't use it.
When switch does bad things, you just learn how to avoid them. That's
how dogma works.

--

-- Pete
Roundhouse Consulting, Ltd. (www.versatilecoding.com)
Author of "The Standard C++ Library Extensions: a Tutorial and
Reference." (www.petebecker.com/tr1book)

Thant Tessman

unread,
Mar 27, 2007, 3:03:15 PM3/27/07
to
Edward Rosten wrote:

> [...] Jumping out of a nested loop requires a
> goto. [...]

Technically it doesn't if your compiler supports tail-call optimization.
Recursive function calls (even mutually recursive function calls) can,
under certain conditions, be converted by the compiler into loops that
use constant space. From the programmer's point of view, jumping out of
a nested loop is nothing more than returning from a function call.

Some programming languages require tail-call optimization as part of
their standard, but at least some C++ compilers will do it as an
optimization.

-thant

--

James Kanze

unread,
Mar 27, 2007, 3:01:15 PM3/27/07
to
On Mar 27, 6:43 pm, "Kirit Sælensminde" <kirit.saelensmi...@gmail.com>
wrote:

> On Mar 27, 5:53 pm, "James Kanze" <james.ka...@gmail.com> wrote:

> > switch ( in.peek() ) {
> > case EOF :
> > in.setstate( ios::failbit ) ;
> > break ;

> > case '[' :
> > in >> match( '[' ) >> x >> y >> match( ']' ) ;
> > break ;

> > case '(' :
> > in >> match( '(' ) >> x >> match( ',' ) >> y >>
> > match( ')' ) ;
> > break ;

> > default :
> > in >> x >> y ;
> > break ;
> > }

> Without getting into the whole "is a switch statement really just a
> glorified goto", does it not suffer one of the problems of goto, that
> being bypassing constructors?

There's no reason to avoid the question: in C++, the switch
statement is nothing but a glorified goto. The problem isn't
with goto, however, but with the program structures it is used
for; one of the cleanest written programs I ever saw was written
in Fortran IV, and it used goto's all over the place. In C++,
we have real, scoped structures for every necessary flow control
(and some totally unnecessary ones:-)), except a true switch or
case statement. So we use the switch statement we have.

And yes, bypassing constructors can be a problem. In anything
but the most trivial switch case, the actual code for each case
should be wrapped in a {}. And if you forget, the compiler will
tell you.

> switch ( 1 ) {
> std::string str;
> case 1: str = "ouch";
> }

> My impression is that this will bypass the constructor. Am I wrong? (I
> really hope that I am).

No. Such code is illegal, according to the C++ standard, and a
compiler diagnostic is required.

--
James Kanze (GABI Software) mailto:james...@gmail.com
Conseils en informatique orient?e objet/
Beratung in objektorientierter Datenverarbeitung
9 place S?mard, 78210 St.-Cyr-l'?cole, France, +33 (0)1 30 23 00 34

--

Pete Becker

unread,
Mar 27, 2007, 6:36:05 PM3/27/07
to
Pete Becker wrote:
> Kirit Sælensminde wrote:
>>
>> Without getting into the whole "is a switch statement really just a
>> glorified goto", does it not suffer one of the problems of goto, that
>> being bypassing constructors?
>>
>> switch ( 1 ) {
>> std::string str;
>> case 1: str = "ouch";
>> }
>>
>> My impression is that this will bypass the constructor. Am I wrong? (I
>> really hope that I am).
>>
>
> No, you're right.

Whoops, too busy being clever. This would bypass the constructor, so
it's ill-formed.

Walter Bright

unread,
Mar 27, 2007, 6:32:20 PM3/27/07
to
James Kanze wrote:
> I do know of at least
> one compiler (for Modula-2), however, that based itself on the
> explicitly written structures, and didn't even try to optimize
> if there was a goto. According to the authors of the compiler,
> this resulted in much faster optimization, at no cost to typical
> (Modula-2) programs.

And who has written an M2 compiler since 1990? Nobody. Yes, I also knew
of compilers written in the 80's that would abandon all optimizations if
there was a goto. And regardless of the justifications put out by the
authors of such, I'll bet the real answer is they were ignorant of well
known compiler technology. A lot of people did write compilers in the
80's who didn't know anything about it. There's nothing slow about the
loop detection algorithms. I implemented them to run on a friggin' 16
bit DOS computer in 1985.

> Of course, most of the optimizing technology that you would have
> been taught in 1982 was developed for Fortran, where you didn't
> have that luxury.

C'mon, James, even Fortran had structured loops (DO 10 I). Fortran's
heyday was the 60's. The state of the art had long since left Fortran
behind in the 70's. Structured programming was well entrenched by 1982.
Structured programming (i.e. goto-less) was the great buzzword of the 70's.

The buzzword of the 80's was object-oriented programming.
The buzzword of the 90's was generic programming.
The buzzword of the 00's is metaprogramming.
The buzzword of the 10's will be (I predict) concurrent programming.

> One could argue that, today, we could do
> better. Still, it's a tried and true technology, and if I were
> writing a compiler today, I'd probably use it, not because I
> want to support goto particularly well, but because I know it
> works, given the number of compilers which use it.

You'd also use it because it's actually *easier* to write the compiler
that way. It really does pay off to read a book on compiler construction
before expending a large portion of your time implementing one <g>.

Vladimir Marko

unread,
Mar 27, 2007, 6:37:14 PM3/27/07
to
On 26 Mar, 23:13, Walter Bright <wal...@digitalmars-nospamm.com>
wrote:

> Vladimir Marko wrote:
> > On 26 Mar, 13:47, Walter Bright <wal...@digitalmars-nospamm.com>
> > wrote:
> >> I regularly use it, probably more than anyone else I know. If you want
a
> >> sample of it in professional code,
seehttp://ftp.digitalmars.com/dmd.zip

> >> and grep for goto in /dmd/src/dmd/
>
> > That's pure C, isn't it? goto is certainly useful in C, but there are
> > better tools for the job in C++.
>
> It's C++. The front end is in C++ to make it easier to connect with
> existing back ends, which are likely to be in C or C++.

OK, it's C++. But it's easy to miss when having just a quick look.
The files are .c, not .C, .cpp, .cc or .cxx, they start by
including deprecated headers and the classes are introduced by
the keyword "struct" with data members at the beginning. So if one
accidentaly opens say mars.h and inifile.c (with free functions in
global namespace) they can easily miss it.

And when I see a function start by declaring a bunch of local
variables my first assumption is that it must be C. If I find that
in a .d file I just can't help thinking something's gone very
wrong there.

> >> 2) combining block exit cleanup code
> > I thought that's what RAII is for in C++.
>
> Yes, you can do it with RAII, but creating classes for the sole purpose
> of manipulating control flow (rather than storing state) is a
> contortion, not clarification.

First, why should I bother creating classes when I can do it with
a few templates? The only valid complaint here is about C++ not
having proper lambda expression support. For simple things
const scope_exit& dummyName = bind(&Foo::Finish,foo);
should do. Well, anonymous references would help too. And before
you mention scope(success) and scope(failure), the problem in
C++ is not with RAII; it's with the std::uncaught_exception being
insufficient to determine whether to execute the code or not.

Second, creating _objects_ "for the sole purpose of manipulating
control flow" is the very best way of writing exception safe (and
IMO also simple and maintainable) code.

> My favorite solution for this is actually the scope guard
> statement:http://www.digitalmars.com/d/exception-safe.html
> invented by Andrei Alexandrescu and Petru Marginean

Is this not RAII? Is my definition of "resource" much broader
than yours?

> >> 3) combining common error exits
>
> > Ehm, is "goto nomatch;" more readable than "return nomatch;" where
> > nomatch
> > is a local enumerator defined at the _beginning_ of the function
> > (where it
> > nicely documents the return values)?
>
> 6 of one, half dozen of the other.

"goto nomatch;" requires the reader to go down to see if there's
something else than the sole return statement. And I thought you
want to "keep [the code] aesthetically where it belongs". (This
quote from http://www.digitalmars.com/d/exception-safe.html is a
little generalised, originaly it applies only to "unwinding code".)

Regards
Vladimir Marko

Walter Bright

unread,
Mar 27, 2007, 6:33:18 PM3/27/07
to
Gerhard Menzl wrote:
> Walter Bright wrote:
>
>> Yes, you can do it with RAII, but creating classes for the sole
>> purpose of manipulating control flow (rather than storing state) is a
>> contortion, not clarification.
>
> An interesting point of view. Do you also consider replacing
> switch(type) constructs by class hierarchies as a contortion?

Consider this excerpt from the D programming language compiler lexer
that scans for the end of a text line:
---------------------
while (1)
{ unsigned char c = *p;
switch (c)
{
case '\n':
p++;
break;

case '\r':
p++;
if (*p == '\n')
p++;
break;

case 0:
case 0x1A:
break;

default:
if (c & 0x80)
{ unsigned u = decodeUTF();
if (u == PS || u == LS)
break;
}
p++;
continue;
}
break;
}
------------------------
Yeah, I think it would be ridiculous to replace this with a class hierarchy.

--

Walter Bright

unread,
Mar 27, 2007, 6:33:59 PM3/27/07
to
Thant Tessman wrote:
> Edward Rosten wrote:
>
>> [...] Jumping out of a nested loop requires a
>> goto. [...]
>
> Technically it doesn't if your compiler supports tail-call optimization.
> Recursive function calls (even mutually recursive function calls) can,
> under certain conditions, be converted by the compiler into loops that
> use constant space. From the programmer's point of view, jumping out of
> a nested loop is nothing more than returning from a function call.
>
> Some programming languages require tail-call optimization as part of
> their standard, but at least some C++ compilers will do it as an
> optimization.

Tail-call optimization doesn't work if there are RAII objects that need
cleaning up.

Daniel T.

unread,
Mar 27, 2007, 9:03:33 PM3/27/07
to
Pete Becker <pe...@versatilecoding.com> wrote:
> Kirit Sælensminde wrote:
> >
> > Without getting into the whole "is a switch statement really just a
> > glorified goto", does it not suffer one of the problems of goto, that
> > being bypassing constructors?
> >
> > switch ( 1 ) {
> > std::string str;
> > case 1: str = "ouch";
> > }
> >
> > My impression is that this will bypass the constructor. Am I wrong? (I
> > really hope that I am).
> >
>
> No, you're right. But you're missing the point. goto is bad, switch is
> good. So when goto does bad things, that proves you shouldn't use it.
> When switch does bad things, you just learn how to avoid them. That's
> how dogma works.

Dijkstra already covered this issue in his paper:

When we include conditional clauses (if B then A), alternative
clauses (if B then A1 else A2), choice clauses as introduced by C. A.
R. Hoare (case[i] of (A1, A2,···, An)),or conditional expressions as
introduced by J. McCarthy (B1 -> E1, B2 -> E2, ···, Bn -> En), the
fact remains that the progress of the process remains characterized
by a single textual index.

--

Walter Bright

unread,
Mar 27, 2007, 9:02:19 PM3/27/07
to
Vladimir Marko wrote:
> On 26 Mar, 23:13, Walter Bright <wal...@digitalmars-nospamm.com>
> wrote:
> OK, it's C++. But it's easy to miss when having just a quick look.
> The files are .c, not .C, .cpp, .cc or .cxx,

I use C++ as "a better C" <g>.

> they start by including deprecated headers
> and the classes are introduced by the keyword "struct"
> with data members at the beginning.

My personal style.

>>>> 2) combining block exit cleanup code
>>> I thought that's what RAII is for in C++.
>> Yes, you can do it with RAII, but creating classes for the sole purpose
>> of manipulating control flow (rather than storing state) is a
>> contortion, not clarification.
>
> First, why should I bother creating classes when I can do it with
> a few templates? The only valid complaint here is about C++ not
> having proper lambda expression support. For simple things
> const scope_exit& dummyName = bind(&Foo::Finish,foo);
> should do. Well, anonymous references would help too.

I view those complaints as being crippling shortcomings. Setting that
aside for the moment, which do you think is more straightforward:

const scope_exit& dummyName = bind(&Foo::Finish,foo);

or:

scope (exit) foo.Finish();

?

> And before you mention scope(success) and scope(failure),

Too late <g>.

> the problem in
> C++ is not with RAII; it's with the std::uncaught_exception being
> insufficient to determine whether to execute the code or not.

I don't understand.

> Second, creating _objects_ "for the sole purpose of manipulating
> control flow" is the very best way of writing exception safe (and
> IMO also simple and maintainable) code.

This is certainly the conventional wisdom. But the cracks in it are
slowly becoming better known, see
http://www.digitalmars.com/d/exception-safe.html and
http://www.ddj.com/dept/cpp/184403758. The biggest crack is when you
have a sequence of operations that must either all succeed or all fail.
RAII doesn't do well with this, and try-finally is even worse.

>> My favorite solution for this is actually the scope guard
>> statement:http://www.digitalmars.com/d/exception-safe.html
>> invented by Andrei Alexandrescu and Petru Marginean
>
> Is this not RAII? Is my definition of "resource" much broader
> than yours?

It isn't RAII any more than try-finally is RAII. Any RAII, try-finally,
or scope guard construct can be mechanically transformed in to any of
the others. For a simple analogy, any if statement can be transformed
into an equivalent while statement - but that doesn't mean we should do so.

The two articles referenced attempt to explain when it is appropriate to
use each of the 3 techniques. I admit the advantages to scope guard
aren't immediately obvious, until one uses them a few times and then
tries to go back to using RAII or try-finally.


>>>> 3) combining common error exits
>>> Ehm, is "goto nomatch;" more readable than "return nomatch;" where
>>> nomatch
>>> is a local enumerator defined at the _beginning_ of the function
>>> (where it
>>> nicely documents the return values)?
>> 6 of one, half dozen of the other.
>
> "goto nomatch;" requires the reader to go down to see if there's
> something else than the sole return statement.

The single-entry, single-exit paradigm has value, too.

Keith H Duggar

unread,
Mar 27, 2007, 11:35:00 PM3/27/07
to
Francis Glassborow wrote:
> Of course the above are my (strongly held) opinions but I would dearly
> like to see a single real example. Every goto I have ever encountered
> disappears when the code is redesigned to be simpler, more readable and
> more maintainable.

Consider Yevgeni Kuzmin's efficient cicrle-drawing algorithm (this
version below evaluates f on a raidus r octant centered at (0,0)):

template < class F > inline
void circle_octant ( int r, F f )
{
int x = r ;
int y = 0 ;
int e = -r / 2 ;

if ( r & 1 ) --e , goto odd ;

even :
f(x,y) ;
if ( y >= x ) return ;
e += y++ ;
if ( e >= 0 ) e -= --x ;
odd :
f(x,y) ;
if ( y >= x ) return ;
e += ++y ;
if ( e >= 0 ) e -= --x ;
goto even ;
}

Note there may be an error or two. I couldn't locate the full paper
on my current harddrive. But I think the above is correct.

Care to make the above "simpler, more readable and more maintainable"?

Keith

Michael K. O'Neill

unread,
Mar 28, 2007, 2:09:08 AM3/28/07
to
"James Kanze" <james...@gmail.com> wrote in message
news:1175014084.8...@y66g2000hsf.googlegroups.com...

> On Mar 27, 6:43 pm, "Kirit Sælensminde" <kirit.saelensmi...@gmail.com>
wrote
> >
> >
> > < snip >

> >
> >
> > Without getting into the whole "is a switch statement really just a
> > glorified goto", does it not suffer one of the problems of goto, that
> > being bypassing constructors?
>
> There's no reason to avoid the question: in C++, the switch
> statement is nothing but a glorified goto. The problem isn't
> with goto, however, but with the program structures it is used
> for; one of the cleanest written programs I ever saw was written
> in Fortran IV, and it used goto's all over the place. In C++,
> we have real, scoped structures for every necessary flow control
> (and some totally unnecessary ones:-)), except a true switch or
> case statement. So we use the switch statement we have.
>
>
> < snip >

It's difficult to see any principled, moral distinction between an "evil"
goto and supposedly "acceptable" constructs like break or continue, or even
an early return.

With an appropriate level of sarcasm, Pete Becker (below) seems to correctly
characterize the "goto" debate as a debate over dogma: goto is "bad" and
other constructs are "good", so when goto does bad things, that proves you
shouldn't use goto, whereas when other constructs do bad things, that only
proves that you have not yet learned how to use them correctly.

Of course the real answer is that any programming technique can be used
poorly, but that does not make them inherently evil/bad. Yes, Dijkstra
showed us that you can re-write code to be goto-free, but that doesn't
necessarily make the code better or clearer. In fact, the re-write often
requires the introduction of condition variables that are logically
unrelated and distinct from the algorithm being implemented.

The battle over goto has been waged for many years, beginning perhaps with
Edsger W. Dijkstra's seminal "Letter" to the ACM in 1968: "Go To Statement
Considered Harmful", Communications of the ACM, Vol. 11, No. 3, March 1968,
pp. 147-148. The Letter can be found all over the Internet; one URL is
http://www.acm.org/classics/oct95/ .

Less known is the marvelously-titled (but somewhat ill-tempered) response
written by Rubin around 20 years after Dijkstra's original article. It also
was published in the "Letters" to the ACM: Rubin, Frank, "'GOTO Considered
Harmful' Considered Harmful" (letter to the editor), Communications of the
ACM, vol. 30, no. 3 (March 1987), pp. 195-6. I had trouble finding that one
on the web, but one URL is
http://paramount.www.ecn.purdue.edu/ParaMount/papers/rubin87goto.pdf .
Here's a nice quote from Rubin's response, which gives a taste of his
viewpoint:

"...[T]he notion that GOTO is harmful is accepted almost universally,
without question or doubt. To many people, 'structured programming' and
'GOTO-less programming' have become synonymous. This has caused
incalculable harm to the field of programming, which has lost an efficacious
tool. It is like butchers banning knives because workers sometimes cut
themselves. Programmers must devise elaborate workarounds, use extra flags,
nest statements excessively, or use gratuitous subroutines. The result is
that GOTO-less programs are harder and costlier to create, test, and modify.
..."

Best regards,
Mike

Alf P. Steinbach

unread,
Mar 28, 2007, 4:14:28 AM3/28/07
to
* Keith H Duggar:

The only difference in the even and odd cases is that 'e' is 1 larger in
the odd case. And this essentially boolean value is represented by the
execution position. Represent it as a variable instead.

template< class F >
void circle_octant( int r, F f )


{
int x = r;
int y = 0;
int e = -r/2;

bool oddStep = !!( r & 1 );

e -= oddStep;
for( ;; )
{
f( x,y );
if( y >= x ) { return ; }
e += y + oddStep;
++y;
oddStep = !oddStep;
if( e >= 0 ) { --x; e -= x; }
}
}

--
A: Because it messes up the order in which people normally read text.
Q: Why is it such a bad thing?
A: Top-posting.
Q: What is the most annoying thing on usenet and in e-mail?

Walter Bright

unread,
Mar 28, 2007, 4:17:55 AM3/28/07
to
Michael K. O'Neill wrote:
> It's difficult to see any principled, moral distinction between an "evil"
> goto and supposedly "acceptable" constructs like break or continue, or even
> an early return.

The one technical issue is that one can use goto to create what is
called an "irreducible flow graph", or in other words, a loop with
multiple entry points. It is impossible to create such with structured code.

Some optimization techniques fail with