From: Andrew Poelstra on
On 2010-04-24, James Kanze <james.kanze(a)gmail.com> wrote:
> On Apr 24, 5:12 pm, "Daniel T." <danie...(a)earthlink.net> wrote:
>> "Leigh Johnston" <le...(a)i42.co.uk> wrote:
>
> [...]
>> In C and C++, goto is sufficiently restricted that as long as
>> your functions are small, it is largely harmless.
>
> In C and C++, if your functions are small enough, goto is
> largely harmless. And also useless. All of the examples I've
> seen defending goto introduce excessively complex functions in
> order to justify it.
>

[dropped alt.comp.programming and alt.lang.asm since my
newsserver rejects an egregious number of cross-posts.]

I often see code like

if(setup1() == 0)
goto fail;

if(setup2() == 0)
goto fail;

if(setup3() == 0)
goto fail;

/* now do stuff */

return 0;
fail:
/* :( */
return 1;


Personally, I would do this as:

if(setup1() &&
setup2() &&
setup3()) {
/* now do stuff */
return 0;
}
else {
/* :( */
return 1;
}

But from a stylistic view, the first version doesn't seem all
that bad. I see it a lot and it doesn't bother me, anyway.

--
Andrew Poelstra
http://www.wpsoftware.net/andrew
From: Daniel T. on
Andrew Poelstra <apoelstra(a)localhost.localdomain> wrote:
> On 2010-04-24, James Kanze <james.kanze(a)gmail.com> wrote:
> > On Apr 24, 1:20 pm, "Leigh Johnston" <le...(a)i42.co.uk> wrote:
> > > "spinoza1111" <spinoza1...(a)yahoo.com> wrote:
> > > > On Apr 24, 6:06 pm, Ali Karaali <ali...(a)gmail.com> wrote:
> > > >
> > > > > I use goto to break nested for loops and I can't see a reason
> > > > > to ban goto.
> > > >
> > > > Why not use break instead? Does the same thing, spares you from
> > > > having to define a label.
> > >
> > > Because break only breaks out of the innermost loop, using goto to
> > > break out of nested loops is one of the few sensible uses of goto.
> >
> > But when do you have to break out of a nested loop? (And of course,
> > the only valid use of break in C++ is to end a case in a switch.
> > Otherwise, it's just a goto in disguise.)
>
> This is just as true in C, according to some people (myself included).
> The only exception I can think of is when you are looping only to set
> the loop index to something.
>
> ie,
>
> for(i = 0; i < 10; ++i)
> if(arr[i].state = READY)
> break;
> /* now use arr[i], or if i is 10, indicate failure. */
>
> The alternative here, using the loop structure, would be:
>
> for(i = 0; i < 10 && arr[i].state != READY; ++i)
> ;
> /* now use arr[i], or if i is 10, indicate failure. */
>
> To me, the latter option looks horrific, plus if you swap the operands
> of &&, you get a very hard-to-spot overrun.

I agree that your for loop with an empty body "looks horrific." However:

int findReady(MyStruct* arr, int size) {
int result = 0;
for ( ; result < size; ++result)
if (arr[result].state == READY)
break;
return result;
}

The above also looks pretty "horrific" to me. (Because of the empty
initialization and the fact that there are two loop exit conditions that
are expressed on two different lines and exit from two different places.
All unnecessarily.)

I would be inclined to do something more like:

int findReady(MyStruct* arr, int size) {
int result = 0;
while (result < size && arr[result].state != READY)
++result;
return result;
}

This example better expresses the end condition of the loop, and doesn't
have any uninitialized variables or empty statement blocks.

Near the beginning of my career, I did code maintenance and I would
sometimes find loops with multiple breaks along with a continue or two.
I learned to fear such constructs even without formerly learning
structured programming.
From: Seebs on
On 2010-04-24, James Kanze <james.kanze(a)gmail.com> wrote:
> In other words, if goto makes the code simpler, it means that
> you haven't found the correct expression of the algorithm.

I don't think that's necessarily the case.

> And of course, the problem isn't with goto, per se. It's with
> the way it is used. But because it can be abused so badly,
> modern languages (including C and C++) provide all of the
> necessary structures (and then some) so you don't have to use
> it.

Of course not. However, you may have to either use it, or use additional
time or storage to produce the same results.

> If goto seems necessary, it's because your function is too big
> and unreadable.

I don't agree. Nested cleanup, in C, often benefits a lot from goto.
It's not always the best choice, but it can dramatically simplify some
functions... And in many cases, breaking them out would require a great
deal of effort to duplicate/pass data which was previously just internal
to a given function.

-s
--
Copyright 2010, all wrongs reversed. Peter Seebach / usenet-nospam(a)seebs.net
http://www.seebs.net/log/ <-- lawsuits, religion, and funny pictures
http://en.wikipedia.org/wiki/Fair_Game_(Scientology) <-- get educated!
From: Seebs on
On 2010-04-25, Andrew Poelstra <apoelstra(a)localhost.localdomain> wrote:
> I often see code like

> if(setup1() == 0)
> goto fail;
>
> if(setup2() == 0)
> goto fail;
>
> if(setup3() == 0)
> goto fail;
>
> /* now do stuff */
>
> return 0;
> fail:
> /* :( */
> return 1;

> Personally, I would do this as:
>
> if(setup1() &&
> setup2() &&
> setup3()) {
> /* now do stuff */
> return 0;
> }
> else {
> /* :( */
> return 1;
> }

> But from a stylistic view, the first version doesn't seem all
> that bad. I see it a lot and it doesn't bother me, anyway.

It gets worse when there's non-trivial work which needs to be done
between the various setup(), and/or they have to interact with more
than one or two local variables. There's also the fairly common
idiom:

if (setup1())
goto fail;

if (setup2())
goto teardown1;

if (setup3())
goto teardown2;

/* various stuff */
if (something_went_wrong)
goto teardown3;
/* more stuff */

teardown3:
teardown3();
teardown2:
teardown2();
teardown1:
teardown1();
fail:
return -1;

This has the advantage that, if later you need to add a setup2_5(), you don't
have to go to multiple different places later in the code and add a
teardown2_5().

In general, I find that overly dogmatic structuring tends to reduce
readability. The "obvious" alternative to the above:

if (!setup1()) {
if (!setup2()) {
if (!setup3()) {
/* various stuff */
if (!something_went_wrong) {
/* more stuff */
}
teardown3();
}
teardown2();
}
teardown1();
}

is, IMHO, less readable and less maintainable. It's harder to track
where you are by looking at indentation, and there's less room on a
default-width screen for writing clear code inside /* more stuff */.

-s
--
Copyright 2010, all wrongs reversed. Peter Seebach / usenet-nospam(a)seebs.net
http://www.seebs.net/log/ <-- lawsuits, religion, and funny pictures
http://en.wikipedia.org/wiki/Fair_Game_(Scientology) <-- get educated!
From: James Dow Allen on
On Apr 24, 9:10 pm, "Daniel T." <danie...(a)earthlink.net> wrote:
> ...
> everyone who is tempted to argue about this issue to start from
> Dijkstra's paper rather than simply asserting that "goto is good"
> without understanding the issues involved.
>
> http://www.u.arizona.edu/~rubinson/copyright_violations/Go_To_Considered_
> Harmful.html

I did click the link, though I'm sure I'd read the paper a few times
earlier.
It has one key sentence which I think is now widely understood:
Edsger W. Dijkstra wrote:
> The unbridled use of the go to statement has an immediate consequence
> that it becomes terribly hard to find a meaningful set of coordinates
> in which to describe the process progress.

(Hmmm. Dijkstra *does* write "UNBRIDLED use of goto". Funny how that
disappears from the pedants' sound-bite summaries.)

Dijkstra speaks of "meaningful ... coordinates ... to describe ..."
I think that when state machines are implemented with goto's, the goto
*helps* to map such "coordinates": the transition rules move you to
state 36 so you ... GOTO state39!

One of my own goto's appears horrendous, but is actually just
a way to go to the appropriate progress point when the "meaningful
coordinates" have been established:
Pseudo-code comparison
http://fabpedigree.com/james/gotoalt.htm
Actual C code
http://fabpedigree.com/james/dbldum.htm

(Warning: if anyone *does* say anything good about my code,
it will be a first, and I'll probably faint from the exhiliration!)

> http://www.u.arizona.edu/~rubinson/copyright_violations/Go_To_Considered_
> Harmful.html

PS: Your newswriter seems to have clipped the link, Daniel, which
I then had to hand-enter. I think Google Groups would have gotten
it right, so you may want to switch to that: :-)
> http://www.u.arizona.edu/~rubinson/copyright_violations/Go_To_Considered_Harmful.html

James Dow Allen