From: Andrew Poelstra on 24 Apr 2010 20:59 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 24 Apr 2010 21:46 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 24 Apr 2010 22:47 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 24 Apr 2010 22:53 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 24 Apr 2010 23:17
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 |