473,395 Members | 1,581 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 473,395 software developers and data experts.

when GOTO makes sense.

K&R pg.66 describes two situations when using goto makes sense. Has
anyone here come across situations where using goto provided the most
elegant solution.

--
http://www.kashmiri-pandit.org/atrocities/index.html

Nov 13 '05 #1
45 2653
Debashish Chakravarty wrote:
K&R pg.66 describes two situations when using goto makes sense. Has
anyone here come across situations where using goto provided the most
elegant solution.


Yes. Sometimes when...

1. There is code with a lot of resource allocation and/or semaphores
being held and...

2. There are many potential points of failure and...

3. The resources need to be freed in a very precise order on failure...

.... goto usage can be the most elegant solution.
Because of #1 it's very important to prevent resource leaks and/or
deadlocks. #2 makes it problematic and error prone (for maintenence
programmers) to do:

if(error_condition) {
free(a);
free(b);
unlock(c);
unlock(d);
free(e);
return -1;
}

at every point where a failure may occur (there may be 10 of them, and
each may be subtly different). It may be better to have something like:
(again, only a contrived example, assuming a, b, c, e are initialize
to NULL, etc)
if(error_condition)
goto err;

/*...*/

err:
/* Order important !! */
if(a) free(a);
if(b) free(b);
if(c) free(c);
unlock(c); /* must unlock c before d */
unlock(d); /* must unlock d before free(e) */
if(e) free(e);
return -1;
}
Mark F. Haigh
mf*****@sbcglobal.net

Nov 13 '05 #2
Debashish Chakravarty <de********@yahoo.com> wrote:
K&R pg.66 describes two situations when using goto makes sense. Has
anyone here come across situations where using goto provided the most
elegant solution.


The classic case is breaking out of a nested loop from the inside.
While people who hate goto for some reason despise such things and
prefer having extra if-checks to account such a condition, its slower,
and just makes your code more complicated.

But another interesting case is with state machines. While the
classic implementation of a state matchine is to simply put a switch
statement inside of a while (1) { ... } loop, this has a drawback of
requiring the switch statement to be execute on every state change (on
modern processors this is much slower than direct gotos.) But as an
alternative, one could simply have one switch statement and rather
than breaks at the end of each case block, simply have gotos to the
blocks that represent the state transition. You have to have labels
that are redundant with the case ...: statements, however this
solution is much faster, and doesn't require that you maintain a state
variable (since the state itself would be redundant with the case
clause that was being executed at any one time) for all states (just
entry and exit of the state machine.)

Finally sometimes its best, for performance reasons to start a loop in
the middle of the body of the loop rather than a start. So you have a
goto just before your do {...} while or for() loop to enter in the
middle of it.

These are probably the most interesting marginal cases where using
goto is the best solution in the C language. The problem is that
there are many other uses of goto which are really really bad. So
much so that people have railed against its usage, and will actually
choose not to do so in any situation. They will lose performance
and/or make their code complicated in all of the above cases. So this
*should* make a good case for improving improving the language so that
these operations can be done *without* goto (for example <break n;> to
jump out of n nested blocks, and <continue case ___;> to jump to a
case within the nearest enclosing switch scope.) However, I don't
know if the C standards committee is open to suggestions such as
these.

--
Paul Hsieh
http://www.pobox.com/~qed/
http://bstring.sf.net/
Nov 13 '05 #3
On Sat, 29 Nov 2003 06:00:40 -0800, Paul Hsieh wrote:

But another interesting case is with state machines. While the
classic implementation of a state matchine is to simply put a switch
statement inside of a while (1) { ... } loop, this has a drawback of
requiring the switch statement to be execute on every state change (on
modern processors this is much slower than direct gotos.) But as an
alternative, one could simply have one switch statement and rather
than breaks at the end of each case block, simply have gotos to the
blocks that represent the state transition. You have to have labels
that are redundant with the case ...: statements, however this
solution is much faster, and doesn't require that you maintain a state
variable (since the state itself would be redundant with the case
clause that was being executed at any one time) for all states (just
entry and exit of the state machine.)


Hmm, I've always implemented state machines with function pointers, like
so:
.... in the header:
typedef void * (*state) (int);
.... in main.c:
while (ch = getnewinput()) {
current = (state)(*current)(ch);
}
}
.... example state: ( this is a very simple DFA )
void *
green (int input) {
switch (input) {
case 'A':
printf("LIGHTS OFF\n");
return &other;
break;
case 'B':
printf("LIGHTS OFF\n");
return &initial;
break;
}
}

Of course, casting function pointers to void and back can lead to
undefined behavior on certain architectures (though I've verified that
this code works on x86 and PPC). But doesn't this seem like a better
solution (and definitely more functional, seeing as it basically emulates
the workings of a functional language), than using gotos?

--
Mike's Patented Blocklist; compile with gcc:

i=0;o(a){printf("%u",i>>8*a&255);if(a){printf(".") ;o(--a);}}
main(){do{o(3);puts("");}while(++i);}

Nov 13 '05 #4
In article <pa***************************@spamblocked.com>,
"Michael B." <us*****@spamblocked.com> wrote:
Of course, casting function pointers to void and back can lead to
undefined behavior on certain architectures (though I've verified that
this code works on x86 and PPC). But doesn't this seem like a better
solution (and definitely more functional, seeing as it basically emulates
the workings of a functional language), than using gotos?


It leads to undefined behavior, that's it. So that makes it in the eyes
of most people a very bad solution, definitely worse than using goto.

It also mixes up "states" and "implementation of code to handle the
action in a given state". Each of your functions doesn't return a state,
it returns a pointer to the code to be executed in that state.

And it adds significantly to the number of lines of code to be written.
In most state machines, the code for each state is quite trivial, so
adding a few lines for every state adds significantly to the lines of
code.
Nov 13 '05 #5
"Mark F. Haigh" <mf*****@sbcglobal.ten> wrote in message news:<zF*******************@newssvr25.news.prodigy .com>...
Debashish Chakravarty wrote:
anyone here come across situations where using goto provided the most
elegant solution.

Yes. Sometimes when...
2. There are many potential points of failure and...
3. The resources need to be freed in a very precise order on failure...


These gotos may sometimes be avoided by replacing
if (! step7())
goto backout7;
if (! step8())
goto backout8;
...
with
if (step7()) {
if (step8()) {
...
}
}
but the cure may be worse than the disease
if there are many levels of nesting.

Another frequent case where goto is better than the alternative is
for (Search; unfinished;) {
for (Subsearch; unfinished;) {
if (WE_WON) {
celebrate();
goto persevere;
}
}
}
lament();
persevere: ;

(Even when loops are not nested, a ``break'' is not quite
enough to avoid this ``goto.'')

I use very few gotos in *final* code, but when cranking out
fresh code, I sometimes write ``goto start_over'' and then decide
later, when I see the full logic, whether to rewrite the loop as
``do'', ``while'' or ``for.'' (In other words, the goto-less
version will be more *readable*, but the *goto* is more *writable*.)

Finally, let me mention my Favorite Goto (tm):
http://freepages.genealogy.rootsweb....ech/dbldum.htm

If one needs to make major changes to the Favorite Goto program,
getting rid of the goto might be the first step, but as is,
it possesses, IMO, a beautiful elegance no non-GOTO version
will have. Can you construct a goto-less equivalent that is
in the same ballpark for speed and readability?

(I have posted the Favorite Goto before on Usenet, receiving
some suggestions which made no sense. Please code, compile and
test your version before sending it to me.)

James
Nov 13 '05 #6
In <3F**************@yahoo.com> Debashish Chakravarty <de********@yahoo.com> writes:
K&R pg.66 describes two situations when using goto makes sense. Has
anyone here come across situations where using goto provided the most
elegant solution.


'Elegant' is in the eye of the beholder. I prefer to speak in terms of
readable code. The code readability decreases exponentially when the
number of nested control structures increases linearly. If a goto can
avoid an additional nesting level, than that goto is probably a "good"
goto. Of course, this is not the only technique for minimising the number
of nested control structures in a function, but one shouldn't
automatically discard it on religious grounds.

Dan
--
Dan Pop
DESY Zeuthen, RZ group
Email: Da*****@ifh.de
Nov 13 '05 #7


James Dow Allen wrote:

<snip>
Finally, let me mention my Favorite Goto (tm):
http://freepages.genealogy.rootsweb....ech/dbldum.htm

If one needs to make major changes to the Favorite Goto program,
getting rid of the goto might be the first step, but as is,
it possesses, IMO, a beautiful elegance no non-GOTO version
will have. Can you construct a goto-less equivalent that is
in the same ballpark for speed and readability?


This MAY (or may not) be the most efficient piece of code on the planet,
but this has to be some of the worst code I've ever seen for
readability. In particular, jumping back and forth between the bodies of
2 separate pairs of nested "for" loops using "goto"s is horrible, and
then having compound conditions like this in a loop:

for (tnum = won = success = 0;
success ? ++won < need : won + ohsize >= need + tnum;
tnum++, P++, success = IS_CONT(pwin)) {

is just ridiculuous too.

By the way, the program hangs on the second sample input provided on the
web site. I would debug it, but I don't want to take the time to
understand it ;-). Ditto for providing a non-goto alternative.

I'm not 100% against gotos, I've just never seen code that uses gotos
that I personally find more readable than the equivalent without gotos.
I recently wrote a short (200 lines or so) program using gotos just to
see if I could learn to appreciate the benefits wrt error-handling, but
once the error-handling became even moderatly complex (i.e. realisitc!)
the initial simplicity afforded by the gotos fell away. I looked at your
code hoping to learn a good way to use goto for readability.

Ed.

Nov 13 '05 #8
On Mon, 1 Dec 2003 05:13:10 UTC, jd*********@yahoo.com (James Dow
Allen) wrote:
I use very few gotos in *final* code, but when cranking out
fresh code, I sometimes write ``goto start_over'' and then decide
later, when I see the full logic, whether to rewrite the loop as
``do'', ``while'' or ``for.'' (In other words, the goto-less
version will be more *readable*, but the *goto* is more *writable*.) Finally, let me mention my Favorite Goto (tm):
http://freepages.genealogy.rootsweb....ech/dbldum.htm
Looks more obscure than needed. A better structure is required.

Use functions to encapsulate details from the flow.
Using the the same functions would remove any need for goto as side
effect.
You've written some loops looking exactly identical. Buildng fuctions
would remove the details from the flow and lets them reused.

Programming starts with design, not hacking.
A well designed program has not a single function but many of them,
each not longer than about 50 lines, doing one specific task. Not
more, not less.

A task gets splitted in What is to do and how is it done. This makes
debugging more easy, helps to understund the flow and is at least more
readable as such a hack as you'd produced.
If one needs to make major changes to the Favorite Goto program,
getting rid of the goto might be the first step, but as is,
it possesses, IMO, a beautiful elegance no non-GOTO version
will have. Can you construct a goto-less equivalent that is
in the same ballpark for speed and readability?


A side effect would be that there is no goto in the whole program.
That is because the need of goto gets superflous by design.

--
Tschau/Bye
Herbert

To buy eComStation 1.1 in germany visit http://www.pc-rosenau.de

Nov 13 '05 #9
On Fri, 28 Nov 2003 22:08:10 -0500, Debashish Chakravarty
<de********@yahoo.com> wrote:
K&R pg.66 describes two situations when using goto makes sense. Has
anyone here come across situations where using goto provided the most
elegant solution.


Yes.

--
Al Balmer
Balmer Consulting
re************************@att.net
Nov 13 '05 #10
"Michael B." <us*****@spamblocked.com> wrote:
On Sat, 29 Nov 2003 06:00:40 -0800, Paul Hsieh wrote:
But another interesting case is with state machines. While the
classic implementation of a state matchine is to simply put a switch
statement inside of a while (1) { ... } loop, this has a drawback of
requiring the switch statement to be execute on every state change (on
modern processors this is much slower than direct gotos.) But as an
alternative, one could simply have one switch statement and rather
than breaks at the end of each case block, simply have gotos to the
blocks that represent the state transition. You have to have labels
that are redundant with the case ...: statements, however this
solution is much faster, and doesn't require that you maintain a state
variable (since the state itself would be redundant with the case
clause that was being executed at any one time) for all states (just
entry and exit of the state machine.)
Hmm, I've always implemented state machines with function pointers, like
so:


Function pointers, computed gotos (for gcc fans) and switch statements
are all roughly the same speed -- i.e., they are all slow pipeline
serializing bottlenecks in modern microprocessors (since the predictor
is likely to be wrong.) And once again, with your array of function
pointers strategy requires that you maintain an index as you do state
transitions. Worse yet, you have to write a bunch of little
function-lets just to handle single state handling and state
transitions.

Your solution is fine from a functionality point of view, but still
cannot hold a candle to a sequence of hand coded gotos in terms of
performance, and even compactness (since you avoid state index
maintence.) The only disadvantage of my method are the hugely
redundant case and goto labels. (You can of course clean this up a
bit with macros.)
[...] Of course, casting function pointers to void and back can lead to
undefined behavior on certain architectures (though I've verified that
this code works on x86 and PPC).
Of course nobody is going to bother you about doing this, even the
group jumped on me when I magicallly coerced a void * into a FILE *
which apparently fails on like 3 obscure machines in the whole world
that noone has ever heard of (and upon which none can read USENET
news.)
[...] But doesn't this seem like a better
solution (and definitely more functional, seeing as it basically emulates
the workings of a functional language), than using gotos?


No ... not unless you were trying to construct state machines on the
fly. And that doesn't come up unless you are trying to do something
like regular expression parsing -- but in those cases I would think
that special casing would tend to still win over such an overly
general method such as you describe.

--
Paul Hsieh
http://www.pobox.com/~qed/
http://bstring.sf.net/
Nov 13 '05 #11
On Mon, 01 Dec 2003 11:25:41 -0600, Ed Morton
<mo****************@lucent.com> wrote:
I'm not 100% against gotos, I've just never seen code that uses gotos
that I personally find more readable than the equivalent without gotos.
I recently wrote a short (200 lines or so) program using gotos just to
see if I could learn to appreciate the benefits wrt error-handling, but
once the error-handling became even moderatly complex (i.e. realisitc!)
the initial simplicity afforded by the gotos fell away. I looked at your
code hoping to learn a good way to use goto for readability.

Ed.


instead of using 'break' in the pseudocode below, i would prefer using
'goto'. Suggestions appreciated. This avoids testing a variable we
just set (in the event something failed). "var is false. Is var
true?" If there is only one label, it seems very readable to me. It
clearly outlines which parts of the code will not be executed if
something fails. The if() test around process(); suggests at first
glance that it may or may not be executed on an error-free pass,
depending on some other condition. Using goto and keeping process()
from being buried keeps this much more clear. It depends on the
situation of course.

To me,

if ( a) { ... }

reads the same as

if (!a) goto skip_this; { ... } skip_this:

especially, and i will be flamed for this, if you consider the opcodes
which will be generated, on the actual real tangible machine(s) on
which it will run. When you think of it this way, it doesn't matter
whether you use goto or not, cos the CPU will (i.e. JUMP type of
instruction).

So you must decide what is readable, and what other people will think
is readable. Bottom line - if people keep asking you why you have all
those 'goto' statements, it's time to cut back.

Remember, C code will be:
1) compiled and executed or
2) interpreted or
3) in a textbook, hopefully with rules and exceptions
============ inefficient, inelegant, recommended ===========

for ( .. ) {
if ( a != b ) {
good=false;
complain();
break;
}
}

if (good) {
process();
}

cleanup_regardless:
cleanup();

============ better? saves one test and one stack variable ===========

for ( .. ) {
if ( a != b ) {
complain();
goto cleanup_regardless;
}
}

process();

cleanup_regardless:
cleanup();

============ ===========

of course, i hope i never see gotos in something like:

if ( (fp = fopen(szFilename)) != NULL ) {
if ( fread (&buf, 1, len, fp) == len ) {
if ( !strncmp ( buf, 4, "JFIF") ) {
process_jfif();
}
}
}
Nov 13 '05 #12


Damn Skippy wrote:
<snip>
instead of using 'break' in the pseudocode below, i would prefer using
'goto'.
A break (or a continue) is just a goto in disguise. In some ways they're
worse - at least a goto has a label associated with it which you can
give a meaningful name. I never use either, except, of course, break in
a switch statment.

Suggestions appreciated.

Since you asked...

<snip>
So you must decide what is readable
That's what I'm after. In most code, I'll cheerfully accept a very small
performance impact in exchange for even a very small gain in readability.
============ inefficient, inelegant, recommended ===========
I'd never recommend this....
for ( .. ) {
if ( a != b ) {
good=false;
complain();
break;
}
}

if (good) {
process();
}

cleanup_regardless:
cleanup();

============ better? saves one test and one stack variable ===========
Yes, if modified as described further down in my response.
for ( .. ) {
if ( a != b ) {
complain();
goto cleanup_regardless;
}
}

process();

cleanup_regardless:
cleanup();

============ ===========
What both of the above are missing is an explicit statement of what gets
you out of the "for" loop, so the next person to work on this code has
no help in understanding what this VERY IMPORTANT condition is that
suddenly changes flow control. Assuming that "a != b" means that the
processor is in overload, I'd write it as something like:

olvdState = STABLE;
for ( ..; .. && ovldState == STABLE; .. ) {
if ( a != b ) {
ovldState = OVERLOADED;
complain();
}
}

if (ovldState = STABLE) {
process();
}

cleanup();

If you had written your goto-version like this:

for ( ..; ..; .. ) {
if ( a != b ) {
complain();
goto overloaded;
}
}

process();

overloaded:
cleanup();

then it's pretty close to the version I wrote without gotos in that it
explicitly tells the reader WHY you're leaving the loop (as opposed to
just what you're going to do after you leave the loop, which is already
clear from the "cleanup()" function name) and yes, I think it's better
than your original version that uses a break.

The main reason I prefer the version that uses a variable is that it
forces the original code author to explicitly state the VERY IMPORTANT
loop exit conditions so the next reader isn't fooled into thinking they
know exactly why the loop terminates until they're in the middle of the
loop and suddenly come across an unexpected, probably unnamed, loop exit.

Sure it's a little more work for the original author to come up with
good names for the variable and it's values, but that's better than the
next guy having to potentially take much longer to have to figure out
that abstraction, possibly under customer pressure to fix or enhance
that and/or other code.

People using gotos typically (but, I assume, not always) create their
labels based on WHAT they're doing at that labelled point rather than
WHY they're doing it. Not being a goto officianado, I can't decide if
that's the right thing to do with a goto or not - you'd end up with more
labels if you use the "WHY" (e.g. since there could be many reasons for
going to a "cleanup" routine) but IMHO you'd have more readable code.
of course, i hope i never see gotos in something like:

if ( (fp = fopen(szFilename)) != NULL ) {
if ( fread (&buf, 1, len, fp) == len ) {
if ( !strncmp ( buf, 4, "JFIF") ) {
process_jfif();
}
}
}


Then don't look at the URL posted elsethread (shudder...) ;-).

Ed.

Nov 13 '05 #13
Ed Morton <mo****************@lucent.com> wrote in message news:<bq********@netnews.proxy.lucent.com>...
James Dow Allen wrote:
Finally, let me mention my Favorite Goto (tm):
http://freepages.genealogy.rootsweb....ech/dbldum.htm
This MAY (or may not) be the most efficient piece of code on the planet,
but this has to be some of the worst code I've ever seen for
readability. In particular, jumping back and forth between the bodies of
2 separate pairs of nested "for" loops using "goto"s is horrible,


Is it really as horrible as it seems? Putting verb participles at the
ends of sentences seems wrong to Englishmen but normal to a German.

I'll certainly admit the structure is bizarrely unusual, but personally I
find it bizarrely elegant! It works only because the two loops manipulate
the same variables in exactly the same way, but once you understand this
fact, it makes sense.

But let me emphasize one key point: The problem this program solves
is non-trivial. *Any* program to solve the problem will take time
to understand. The question isn't whether my program takes a while
to understand, but how that time compares with an efficient alternative
to *solve the same problem.*

It did not take me long to write this program, and many people have
downloaded it for its intended application. Does no one care to invest
a little time to prove there is an efficient readable alternative?
then having compound conditions like this in a loop:

for (tnum = won = success = 0;
success ? ++won < need : won + ohsize >= need + tnum;
I could have added comments, but the C isn't too opaque.
Reading left to right,
did contractors SUCCESS-fully win the trick? If so, increment the
number of tricks they've WON and compare it with the number they NEED
for their contract.... tnum++, P++, success = IS_CONT(pwin)) {

is just ridiculuous too.
Perhaps I should enter it in the Obfuscated C contest. :-)
I often provide newlines to break up such long expressions; would
that address your complaint? Is an expression terminated with
comma *really* harder to understand than one terminated with semicolon?
By the way, the program hangs on the second sample input provided on the
web site.
How long did you let it run? Experts spend hours on that puzzle
without getting it, I hope you gave your Pentium a few minutes.
This is the first failure report I've had; I'd appreciate a core dump.

Someone else wrote: Looks more obscure than needed. A better structure is required.


No question that this 200-line program is much harder to understand
than a typical 500-line program, but that's not the proper question.

The question is, how does its difficulty compare with an alternative
program *that solves the same problem.* Since my program provides
all the necessary algorithm details, I do not believe rewriting the
program is a significant challenge to a good programmer.

When someone demonstrates a working program almost as efficient and
more readable than mine, I'll "eat my hat." Until then, your words
are just idle pedantry.

James
Nov 13 '05 #14


James Dow Allen wrote:
<snip>
It did not take me long to write this program, and many people have
downloaded it for its intended application. Does no one care to invest
a little time to prove there is an efficient readable alternative?
It's not a little time. I'm sure my total lack of knowledge about bridge
doesnt help, but that's kinda my point.
then having compound conditions like this in a loop:

for (tnum = won = success = 0;
success ? ++won < need : won + ohsize >= need + tnum;

I could have added comments, but the C isn't too opaque.
Reading left to right,
did contractors SUCCESS-fully win the trick? If so, increment the
number of tricks they've WON and compare it with the number they NEED
for their contract....
tnum++, P++, success = IS_CONT(pwin)) {

is just ridiculuous too.

Perhaps I should enter it in the Obfuscated C contest. :-)
I often provide newlines to break up such long expressions; would
that address your complaint?


No, some well-named intermediate variables, functions and/or macros
would address my complaint.

Is an expression terminated with comma *really* harder to understand than one terminated with semicolon?
No. It was the loop termination condition that was the hardest to
understand. I don't mean I can't read the C, I just don't know what the
abstraction is for the C (i.e. what it "means").
By the way, the program hangs on the second sample input provided on the
web site.

How long did you let it run? Experts spend hours on that puzzle
without getting it, I hope you gave your Pentium a few minutes.
This is the first failure report I've had; I'd appreciate a core dump.


I was wrong, it doesn't hang. It does just take a few minutes. Since the
first sample terminated within about a second, I expected the second to
do the same. Perhaps a warning about that on the web page and/or
progress reports from the tool would be useful?
Someone else wrote:
Looks more obscure than needed. A better structure is required.

No question that this 200-line program is much harder to understand
than a typical 500-line program, but that's not the proper question.

The question is, how does its difficulty compare with an alternative
program *that solves the same problem.* Since my program provides
all the necessary algorithm details, I do not believe rewriting the
program is a significant challenge to a good programmer.


But it does provide a significant challenge because it's missing all the
abstractions for what the code is doing, so someone who doesn't know the
domain can read the code and understand what's happening to the
variables, etc., but not why it's happening and without the relevant
domain expertise couldn't come up with the right abstractions for a good
modified version of the code.
When someone demonstrates a working program almost as efficient and
more readable than mine, I'll "eat my hat."
Well, if you decomposed what you have into a few small functions (with
their own local variables rather than just the slew of them at the start
of "main()" being promoted to global) and provided some good, abstract
comments, then you'd stand an excellent chance of getting a meal ;-).

Until then, your words are just idle pedantry.
You can dismiss my comments if you like, but I wasn't pedantic about
anything. I didn't say anything like "this code uses goto and therefore
is bad" I said "This code is hard to read, and here's some examples of why".

Ed.
James


Nov 13 '05 #15
Debashish Chakravarty <de********@yahoo.com> wrote in message news:<3F**************@yahoo.com>...
K&R pg.66 describes two situations when using goto makes sense. Has
anyone here come across situations where using goto provided the most
elegant solution.


Another very useful case:

if (..complex stuff..) {
do_something ();
if (...other complex stuff) goto eelse;
... do stuff ...
} else eelse: {
... do the else case ...
}

Once you do this, you'll want to do it all the time.
Nov 13 '05 #16


stelios xanthakis wrote:
Debashish Chakravarty <de********@yahoo.com> wrote in message news:<3F**************@yahoo.com>...
K&R pg.66 describes two situations when using goto makes sense. Has
anyone here come across situations where using goto provided the most
elegant solution.

Another very useful case:

if (..complex stuff..) {
do_something ();
if (...other complex stuff) goto eelse;
... do stuff ...
} else eelse: {
... do the else case ...
}


This is clearer:

status = INCOMPLETE;
if (..complex stuff..) {
do_something ();
if (! ...other complex stuff) {
... do stuff ...
status = COMPLETE;
}
}
if (status == INCOMPLETE) {
... do the else case ...
}

Of course, In a real program I'd have a variable name and values that
accurately reflect the abstract conditions that are true at both of the
assignment points for "status" above.
Once you do this, you'll want to do it all the time.


Not really.

Ed.

Nov 13 '05 #17
Ed Morton <mo****************@lucent.com> wrote in message news:<bq********@netnews.proxy.lucent.com>...
stelios xanthakis wrote:
Debashish Chakravarty <de********@yahoo.com> wrote in message news:<3F**************@yahoo.com>...
K&R pg.66 describes two situations when using goto makes sense. Has
anyone here come across situations where using goto provided the most
elegant solution.

Another very useful case:

if (..complex stuff..) {
do_something ();
if (...other complex stuff) goto eelse;
... do stuff ...
} else eelse: {
... do the else case ...
}


This is clearer:

status = INCOMPLETE;
if (..complex stuff..) {
do_something ();
if (! ...other complex stuff) {
... do stuff ...
status = COMPLETE;
}
}
if (status == INCOMPLETE) {
... do the else case ...
}


Right. Only "problem" is that now we have two statements (actually 3 statements
and a variable). So everything has to be enclosed in { } if the above
is, say, the body of a for(;;).
This is a personal preference of course with little practical use.

Stelios
Nov 13 '05 #18


stelios xanthakis wrote:
Ed Morton <mo****************@lucent.com> wrote in message news:<bq********@netnews.proxy.lucent.com>...
stelios xanthakis wrote: <snip>
Another very useful case:

if (..complex stuff..) {
do_something ();
if (...other complex stuff) goto eelse;
... do stuff ...
} else eelse: {
... do the else case ...
}
This is clearer:

status = INCOMPLETE;
if (..complex stuff..) {
do_something ();
if (! ...other complex stuff) {
... do stuff ...
status = COMPLETE;
}
}
if (status == INCOMPLETE) {
... do the else case ...
}

Right. Only "problem" is that now we have two statements (actually 3 statements
and a variable). So everything has to be enclosed in { } if the above
is, say, the body of a for(;;).


Which it should be anyway to avoid someone in future coming along and
adding a statement which they think is related to the "for" but actually
falls outside it or pushes the existing code outside of it. That's a
very common bug when modifying code that doesn't use braces on every
loop and "if". There's been so many times I've seen something like this:

if (x)
y();

get changed to:

if (x)
y();
z();

Some people write:

if (x) y();

to make the distincion clearer for single-statement cases, but it seems
simpler to me to just always uses the braces (and there are implications
for some source code control systems in a multi-user environment) and
that doesn't apply in this particular case anyway.
This is a personal preference of course with little practical use.
No, it's about increasing the clarity of your code for speed of
understanding by the next person to enhance it and reducing the risk of
someone in future introducing a bug when they modify it (i.e.
"future-proofing") and it's a 100% practical technique.

Ed.
Stelios


Nov 13 '05 #19
On 4 Dec 2003 06:03:20 -0800, ma****@freemail.gr (stelios xanthakis)
wrote:
}
if (status == INCOMPLETE) {
... do the else case ...
}


Right. Only "problem" is that now we have two statements (actually 3 statements
and a variable). So everything has to be enclosed in { } if the above
is, say, the body of a for(;;).


And, imo, this is a good thing. Braces are free, and useful.

--
Al Balmer
Balmer Consulting
re************************@att.net
Nov 13 '05 #20
In <bq********@netnews.proxy.lucent.com> Ed Morton <mo****************@lucent.com> writes:
falls outside it or pushes the existing code outside of it. That's a
very common bug when modifying code that doesn't use braces on every
loop and "if". There's been so many times I've seen something like this:

if (x)
y();

get changed to:

if (x)
y();
z();


That's the kind of mistake one is not very likely to repeat, after getting
burned once. So, there is no need to resort to braces in order to avoid
it.

Dan
--
Dan Pop
DESY Zeuthen, RZ group
Email: Da*****@ifh.de
Nov 13 '05 #21


Dan Pop wrote:
In <bq********@netnews.proxy.lucent.com> Ed Morton <mo****************@lucent.com> writes:

falls outside it or pushes the existing code outside of it. That's a
very common bug when modifying code that doesn't use braces on every
loop and "if". There's been so many times I've seen something like this:

if (x)
y();

get changed to:

if (x)
y();
z();

That's the kind of mistake one is not very likely to repeat, after getting
burned once. So, there is no need to resort to braces in order to avoid
it.


I agree it's not a mistake that one person will make many times, but
it's a mistake that many people will make once, so it is still desirable
to use braces. Typing those couple of extra characters is no big deal
and is well worth the extra second or so of typing if it can avoid a
future bug being introduced. It also removes much of the need for using
"do { ... } while(0)" in compound-statement macros (though, to be
honest, I do that too since my macros are often used in other peoples code).

Ed.
Dan


Nov 13 '05 #22
On 4 Dec 2003 15:56:35 GMT, Da*****@cern.ch (Dan Pop) wrote:
In <bq********@netnews.proxy.lucent.com> Ed Morton <mo****************@lucent.com> writes:
falls outside it or pushes the existing code outside of it. That's a
very common bug when modifying code that doesn't use braces on every
loop and "if". There's been so many times I've seen something like this:

if (x)
y();

get changed to:

if (x)
y();
z();


That's the kind of mistake one is not very likely to repeat, after getting
burned once. So, there is no need to resort to braces in order to avoid
it.

Dan


The problem is that for real software products, maintained over a
number of years, it's not "one", but many.

--
Al Balmer
Balmer Consulting
re************************@att.net
Nov 13 '05 #23
In <4d********************************@4ax.com> Alan Balmer <al******@att.net> writes:
On 4 Dec 2003 15:56:35 GMT, Da*****@cern.ch (Dan Pop) wrote:
In <bq********@netnews.proxy.lucent.com> Ed Morton <mo****************@lucent.com> writes:
falls outside it or pushes the existing code outside of it. That's a
very common bug when modifying code that doesn't use braces on every
loop and "if". There's been so many times I've seen something like this:

if (x)
y();

get changed to:

if (x)
y();
z();


That's the kind of mistake one is not very likely to repeat, after getting
burned once. So, there is no need to resort to braces in order to avoid
it.

Dan


The problem is that for real software products, maintained over a
number of years, it's not "one", but many.


People who maintain software don't actually test the changes they make?

If I change a bit of code, it is because I want to alter its behaviour.
The next thing after doing it is testing it, to see if I got it right.
And if I didn't get it right, I find my bug(s) and fix the code.

Do I have some weird ideas about what software maintenance means?

Dan
--
Dan Pop
DESY Zeuthen, RZ group
Email: Da*****@ifh.de
Nov 13 '05 #24


On 12/4/2003 12:42 PM, Dan Pop wrote:
<snip>
People who maintain software don't actually test the changes they make?

If I change a bit of code, it is because I want to alter its behaviour.
The next thing after doing it is testing it, to see if I got it right.
And if I didn't get it right, I find my bug(s) and fix the code.

Do I have some weird ideas about what software maintenance means?


Only if you think that any of the following is true:

a) There's no cost associated with finding a bug, fixing it, and retesting.
b) During developer-testing, every developer catches every bug they introduced.
c) All software can be tested thoroughly in a cheap development environment
(e.g. off the potentially expensive production hardware).

Ed.

Nov 13 '05 #25
In article <bq********@netnews.proxy.lucent.com>,
Ed Morton <mo****************@lucent.com> wrote:
There's been so many times I've seen something like this:

if (x)
y();

get changed to:

if (x)
y();
z();


Are you teaching courses "C for talentless beginners" ?

I cannot remember seeing that mistake being made in twenty years.
Nov 13 '05 #26


Christian Bau wrote:
In article <bq********@netnews.proxy.lucent.com>,
Ed Morton <mo****************@lucent.com> wrote:

There's been so many times I've seen something like this:

if (x)
y();

get changed to:

if (x)
y();
z();

Are you teaching courses "C for talentless beginners" ?


No, I teach behavioral modeling, but I do inspect a lot of code written
by people with less experience.
I cannot remember seeing that mistake being made in twenty years.


Then you've been incredibly fortunate or don't get to inspect a lot of
code written by relative newcomers or have missed many mistakes.

Ed.

Nov 13 '05 #27
Ed Morton <mo****************@lucent.com> wrote in message news:<bq********@netnews.proxy.lucent.com>...

First: I did appreciate your words and your taking the time to rerun
the program. Sorry if I sounded irritable.
No. It was the loop termination condition that was the hardest to
understand. I don't mean I can't read the C, I just don't know what the
abstraction is for the C (i.e. what it "means").
The program does have a few comments, including one immediately
before the for statement you snipped: /* Loop to play tricks forward until the outcome is conclusive */
for (tnum = won = success = 0;
success ? ++won < need : won + ohsize >= need + tnum;
tnum++, P++, success = IS_CONT(pwin)) {
I assumed an understanding of whist and game search -- the loop
terminates when it is known either that contract will succeed or
won't succeed (and "success" will tell you which.)
I was wrong, it doesn't hang. It does just take a few minutes.
To change the subject, I was pretty sure the program would
run the 2nd input if it could run the 1st. Why? *Because it doesn't
rely on anything.* Some programs have code like
foogle_gark(CanonPrinter, DVI_Level17, REV14_3);
/* remember to ask Tony if we need to change this for
* Rev 14.4 (when line speed exceeds BAUDLIMIT_39) */
My program depended only on printf(), etc. which haven't changed
since the Pleistocene. And even the cheapest cell phone today
has enough memory to run it.
When someone demonstrates a working program almost as efficient and
more readable than mine, I'll "eat my hat."


Well, if you decomposed what you have into a few small functions (with
their own local variables ...)


Studying the program I believe you'll find that to be undoable.
You'll either need lots of global variables, or unwieldy state-
passing in both directions.
Until then, your words
are just idle pedantry.


You can dismiss my comments if you like, but I wasn't pedantic about
anything. I didn't say anything like "this code uses goto and therefore
is bad" I said "This code is hard to read, and here's some examples of why".


I apologize. My point was very badly phrased and, anyway, directed
more at another poster who over-generalized. I stand by my essential
point: My 200-line program is harder to read than a 500-line program,
but many programmers would construct a 2000-line solution if they could
do it all. Let's wait till the alternative is on display before
declaring it more readable.

James
Nov 13 '05 #28
In <3F**************@lucent.com> Ed Morton <mo****************@lucent.com> writes:


On 12/4/2003 12:42 PM, Dan Pop wrote:
<snip>
People who maintain software don't actually test the changes they make?

If I change a bit of code, it is because I want to alter its behaviour.
The next thing after doing it is testing it, to see if I got it right.
And if I didn't get it right, I find my bug(s) and fix the code.

Do I have some weird ideas about what software maintenance means?


Only if you think that any of the following is true:

a) There's no cost associated with finding a bug, fixing it, and retesting.
b) During developer-testing, every developer catches every bug they introduced.
c) All software can be tested thoroughly in a cheap development environment
(e.g. off the potentially expensive production hardware).


You're ignoring the punctual nature of the issue. There is no need to
perform a full retesting of the application, only the correctness of the
changes made needs to be tested, and this is, usually, far easier.

Anyone who changes the code and doesn't test his changes should be
kicked out of this profession.

Dan
--
Dan Pop
DESY Zeuthen, RZ group
Email: Da*****@ifh.de
Nov 13 '05 #29


Dan Pop wrote:
In <3F**************@lucent.com> Ed Morton <mo****************@lucent.com> writes:
On 12/4/2003 12:42 PM, Dan Pop wrote:
<snip> <snip>
Do I have some weird ideas about what software maintenance means?
Only if you think that any of the following is true:

a) There's no cost associated with finding a bug, fixing it, and retesting.
b) During developer-testing, every developer catches every bug they introduced.
c) All software can be tested thoroughly in a cheap development environment
(e.g. off the potentially expensive production hardware).

You're ignoring the punctual nature of the issue.


Not at all.

There is no need to perform a full retesting of the application, only the correctness of the
changes made needs to be tested, and this is, usually, far easier.
Of course rerunning one or 2 tests is easier/cheaper than retesting the
whole code. No-one suggested otherwise.
Anyone who changes the code and doesn't test his changes should be
kicked out of this profession.
s/should/will but that also has nothing whatsoever to do with anything I
said.

Ed.
Dan


Nov 13 '05 #30
Dan Pop wrote:
Ed Morton <mo****************@lucent.com> writes:

.... snip ...

Only if you think that any of the following is true:

a) There's no cost associated with finding a bug, fixing it, and
retesting.
b) During developer-testing, every developer catches every bug
they introduced.
c) All software can be tested thoroughly in a cheap development
environment (e.g. off the potentially expensive production
hardware).


You're ignoring the punctual nature of the issue. There is no
need to perform a full retesting of the application, only the
correctness of the changes made needs to be tested, and this is,
usually, far easier.

Anyone who changes the code and doesn't test his changes should
be kicked out of this profession.


Such changes have been known to affect seemingly totally unrelated
functions. Which is why having a fully automated regression test
suite available is invaluable. Such a test suite should be
generated with the original application, but often is ignored.

--
Chuck F (cb********@yahoo.com) (cb********@worldnet.att.net)
Available for consulting/temporary embedded and systems.
<http://cbfalconer.home.att.net> USE worldnet address!
Nov 13 '05 #31
In <3F***************@yahoo.com> CBFalconer <cb********@yahoo.com> writes:
Dan Pop wrote:
Ed Morton <mo****************@lucent.com> writes:
... snip ...
>
>Only if you think that any of the following is true:
>
>a) There's no cost associated with finding a bug, fixing it, and
> retesting.
>b) During developer-testing, every developer catches every bug
> they introduced.
>c) All software can be tested thoroughly in a cheap development
> environment (e.g. off the potentially expensive production
> hardware).


You're ignoring the punctual nature of the issue. There is no
need to perform a full retesting of the application, only the
correctness of the changes made needs to be tested, and this is,
usually, far easier.

Anyone who changes the code and doesn't test his changes should
be kicked out of this profession.


Such changes have been known to affect seemingly totally unrelated
functions.


It doesn't matter. You simply test their impact on the program behaviour.
If they break something, it doesn't matter where that something is: you
track it and fix it.
Which is why having a fully automated regression test
suite available is invaluable. Such a test suite should be
generated with the original application, but often is ignored.


Especially when generating it is 10 times or more expensive than
developing the application. Which is often the case with complex
applications (e.g. compilers), so you use incomplete testing procedures.

However, when you make a punctual change, it is usually possible to
completely test its effects.

Dan
--
Dan Pop
DESY Zeuthen, RZ group
Email: Da*****@ifh.de
Nov 13 '05 #32


James Dow Allen wrote:
Ed Morton <mo****************@lucent.com> wrote in message news:<bq********@netnews.proxy.lucent.com>...

First: I did appreciate your words and your taking the time to rerun
the program. Sorry if I sounded irritable.


Not at all. Likewise, I appologise if I was rude or sounded offended.

I've added an "OT" label to the subject as I'm about to talk about
algorithms rather than ANSI C:

I took another look at the code and, though I don't get the details, the
comments sound like you're (very roughly) attempting to deal the cards
until some predefined outcome, and backtracking when you hit dead-ends.
If so, did you consider using, say, bit-state-hashing with a depth-first
(recursive-descent) algorithm, e.g. something like this pseudo-code:

play() {
deal(); /* determine possible next states from the
* current state, e.g. card hand combinations.
*/
for (state in possibleStates) {
if (state == the_desired_result) {
return;
} else {
idx = hash(state);
if (hashTbl[idx] == 0) {
/* This is a new configuration
* so continue
*/
hashTbl[idx] = 1;
play();
}
/* else, we've seen this configuration
* before so move on or backtrack
*/
}
}
}

main() {
bool hashTbl[size] = { 0 };
play();
printState(state);
}

Regards,

Ed.

Nov 13 '05 #33
James Dow Allen wrote:

Ed Morton <mo****************@lucent.com> wrote in message news:<bq********@netnews.proxy.lucent.com>...

First: I did appreciate your words and your taking the time to rerun
the program. Sorry if I sounded irritable.
No. It was the loop termination condition that was the hardest to
understand. I don't mean I can't read the C, I just don't know what the
abstraction is for the C (i.e. what it "means").
The program does have a few comments, including one immediately
before the for statement you snipped:
/* Loop to play tricks forward until the outcome is conclusive */
for (tnum = won = success = 0;
success ? ++won < need : won + ohsize >= need + tnum;
tnum++, P++, success = IS_CONT(pwin)) {


I assumed an understanding of whist and game search -- the loop
terminates when it is known either that contract will succeed or
won't succeed (and "success" will tell you which.)
I was wrong, it doesn't hang. It does just take a few minutes.


To change the subject, I was pretty sure the program would
run the 2nd input if it could run the 1st. Why? *Because it doesn't
rely on anything.* Some programs have code like
foogle_gark(CanonPrinter, DVI_Level17, REV14_3);
/* remember to ask Tony if we need to change this for
* Rev 14.4 (when line speed exceeds BAUDLIMIT_39) */
My program depended only on printf(), etc. which haven't changed
since the Pleistocene. And even the cheapest cell phone today
has enough memory to run it.
When someone demonstrates a working program almost as efficient and
more readable than mine, I'll "eat my hat."


Well, if you decomposed what you have into a few small functions (with
their own local variables ...)


Studying the program I believe you'll find that to be undoable.
You'll either need lots of global variables, or unwieldy state-
passing in both directions.
Until then, your words
are just idle pedantry.


You can dismiss my comments if you like, but I wasn't pedantic about
anything. I didn't say anything like "this code uses goto and therefore
is bad" I said "This code is hard to read, and here's some examples of why".


I apologize. My point was very badly phrased and, anyway, directed
more at another poster who over-generalized. I stand by my essential
point: My 200-line program is harder to read than a 500-line program,


All other things being equal, this is almost never the case. Simply
by fact of the program having more stuff in it, it will be somewhat
harder to read. This a variaiton of Strunk and White's "Omit needless
words".

But this is stated in the absence of a lot of other information
that would be necessary to really evaluate a comparison between
the two. A factor of 2.5 is very significant.
but many programmers would construct a 2000-line solution if they could
do it all. Let's wait till the alternative is on display before
declaring it more readable.

James

--
Les Cargill
Nov 13 '05 #34
James Dow Allen wrote:
Ed Morton <mo****************@lucent.com> wrote in message

First: I did appreciate your words and your taking the time to
rerun the program. Sorry if I sounded irritable.
No. It was the loop termination condition that was the hardest
to understand. I don't mean I can't read the C, I just don't
know what the abstraction is for the C (i.e. what it "means").

.... snip ...

I too tried it out, and all seems correct after some repairs, such
as the appropriate #includes, and replacing 'index' with 'strchr'.

It is wanting in input checking. The use of scanf is fatal. I
especially discovered this when a typo in one input hand caused a
12 card hand, and the result announced success after 12 tricks!
My first attempt to feed it a hand used something like "S AKJ543"
etc. and resulted in segfaults. This is where functional
separation greatly eases improvement.

--
Chuck F (cb********@yahoo.com) (cb********@worldnet.att.net)
Available for consulting/temporary embedded and systems.
<http://cbfalconer.home.att.net> USE worldnet address!
Nov 13 '05 #35
Dan Pop wrote:
CBFalconer <cb********@yahoo.com> writes:

... snip ...

Which is why having a fully automated regression test
suite available is invaluable. Such a test suite should be
generated with the original application, but often is ignored.


Especially when generating it is 10 times or more expensive
than developing the application. Which is often the case with
complex applications (e.g. compilers), so you use incomplete
testing procedures.


By the very nature of the beast tests are never complete. If they
were we could prove the absence of bugs.

IMO this is an outstandingly poor example of something hard to
regression test. A compiler has to deal with known syntax,
rejecting much, and the code snippets are relatively easy to
create. I know of no important compilers without such a suite.

However I have found no /reasonable/ way to regression test my
nmalloc package, since the pointers it returns depend on the state
of the rest of the machine.

--
Chuck F (cb********@yahoo.com) (cb********@worldnet.att.net)
Available for consulting/temporary embedded and systems.
<http://cbfalconer.home.att.net> USE worldnet address!
Nov 13 '05 #36
Les Cargill <lc******@worldnet.att.net> wrote in message news:<3F***************@worldnet.att.net>...
James Dow Allen wrote:
... I stand by my essential
point: My 200-line program is harder to read than a 500-line program,


All other things being equal, this is almost never the case. Simply
by fact of the program having more stuff in it, it will be somewhat
harder to read. This a variaiton of Strunk and White's "Omit needless
words".


Although your comment appears contrary to mine, I assume you
realize you are strongly taking my side in this debate.

No one has deigned to display any alternative program, but
if any of the posters have actually spent any effort towards that
goal I'm sure they will agree the "structured" alternative must have
many more keystrokes in it. ... And if posters claim otherwise,
but find it too difficult to modify this 200-liner, ... well
I'll avoid the term "idle pedantry" but just say that either their
love or skill for programming isn't enough.

* * * *

Addressing some other comments, I thought my discussion made it
*very clear* that the example program was deliberately streamlined
to demonstrate algorithmic simplicity and a unique control flow,
and was *not* intended as an "industrial strength" user-friendly
application. Hence, comments like "avoid scanf()" are at cross purpose.

James
Nov 13 '05 #37
Ed Morton <mo****************@lucent.com> wrote in message news:<bq********@netnews.proxy.lucent.com>...
I took another look at the code and, though I don't get the details, the
comments sound like you're (very roughly) attempting to deal the cards
until some predefined outcome, and backtracking when you hit dead-ends.
If so, did you consider using, say, bit-state-hashing with a depth-first
(recursive-descent) algorithm, e.g. something like this pseudo-code:...


The program is one of several example programs at that site.
Unfortunately the webpage doesn't have an appropriate Back button or
you might have stumbled on further discussion and examples.
(I'll add such a Back link, but it didn't seem fully necessary:
you can rubout the last part of the URL and get the Index page for
that directory. The double-dummy program is introduced in Lesson 9.)

I've written other game-search programs, usually similar to your
description, and at least three other example programs at the website
fit that category, none similar to the Whist program.

FWIW, (drumroll), it was my program that first solved the game of
Connect-Four. (That program didn't happen to have "goto", BTW. :-)

BTW, typical games progress
Black, White, Black, White, Black, White, ...
but Whist progresses
N, E, S, W, determine_who_leads, S, W, N, E, determine_who_leads, etc.
This complication is a major reason that more traditional control
flow would become more complicated than the Favorite Goto(tm) does.

James
Nov 13 '05 #38
Debashish Chakravarty <de********@yahoo.com> wrote in message news:<3F**************@yahoo.com>...
K&R pg.66 describes two situations when using goto makes sense. Has
anyone here come across situations where using goto provided the most
elegant solution.


Breaking out of complex loops?? That's the O'Reilly example at any rate.
Nov 13 '05 #39
In <3F***************@yahoo.com> CBFalconer <cb********@yahoo.com> writes:
Dan Pop wrote:
CBFalconer <cb********@yahoo.com> writes:
>>
>... snip ...
>Which is why having a fully automated regression test
>suite available is invaluable. Such a test suite should be
>generated with the original application, but often is ignored.


Especially when generating it is 10 times or more expensive
than developing the application. Which is often the case with
complex applications (e.g. compilers), so you use incomplete
testing procedures.


By the very nature of the beast tests are never complete. If they
were we could prove the absence of bugs.


Never is too strong. If the full set of inputs is reasonably small,
the brute force approach is doable. In some other cases, it is possible
to identify a problematic subset of inputs that need testing (if they
are correctly handled, it is possible to prove that anything else will
be correctly handled). But, often enough, NOTHING can replace the
testing (usually involuntarily) performed by the real world users of your
application.
IMO this is an outstandingly poor example of something hard to
regression test. A compiler has to deal with known syntax,
rejecting much, and the code snippets are relatively easy to
create. I know of no important compilers without such a suite.
You forgot to engage your brain, again. I know of no important
compilers without such a suite, either, yet I know of no important
compiler which is bug free. Which makes it an outstandingly *good*
example of something hard to test.
However I have found no /reasonable/ way to regression test my
nmalloc package, since the pointers it returns depend on the state
of the rest of the machine.


If you have problems testing a malloc package, it's most likely due to its
extremely bad design.

Dan
--
Dan Pop
DESY Zeuthen, RZ group
Email: Da*****@ifh.de
Nov 13 '05 #40


On 12/7/2003 4:00 PM, Barbrawl McBribe wrote:
Debashish Chakravarty <de********@yahoo.com> wrote in message news:<3F**************@yahoo.com>...
K&R pg.66 describes two situations when using goto makes sense. Has
anyone here come across situations where using goto provided the most
elegant solution.

Breaking out of complex loops?? That's the O'Reilly example at any rate.


So, imagine you have to maintain some code. You're new to the domain, trying to
make sense of 1000 lines of code in a hurry to fix a problem that a customer is
threatening to apply penalty clauses for. You're knee deep in, say, a complex
nested loop and suddenly, after a test on a couple of variables and a function
return code, you find a line that says "goto cleanup;". Can you say
"Aaaarrgggghhh!!!!"? Wouldn't a nice little variable that describes the
condition under which you're exiting the loop be a more pleasant discovery?

Ed.

Nov 13 '05 #41
Dan Pop wrote:
CBFalconer <cb********@yahoo.com> writes:
.... snip ...
However I have found no /reasonable/ way to regression test my
nmalloc package, since the pointers it returns depend on the
state of the rest of the machine.


If you have problems testing a malloc package, it's most likely
due to its extremely bad design.


I think it is high time for you to take Richards refresher course
in Reading for Comprehension, after which you can consider the
"/reasonable/" and "regression test" above, and the implication
(from the snipped portion) of "automated".

--
Chuck F (cb********@yahoo.com) (cb********@worldnet.att.net)
Available for consulting/temporary embedded and systems.
<http://cbfalconer.home.att.net> USE worldnet address!
Nov 13 '05 #42
In <3F***************@yahoo.com> CBFalconer <cb********@yahoo.com> writes:
Dan Pop wrote:
CBFalconer <cb********@yahoo.com> writes:

... snip ...
> However I have found no /reasonable/ way to regression test my
> nmalloc package, since the pointers it returns depend on the
> state of the rest of the machine.


If you have problems testing a malloc package, it's most likely
due to its extremely bad design.


I think it is high time for you to take Richards refresher course
in Reading for Comprehension, after which you can consider the
"/reasonable/" and "regression test" above, and the implication
(from the snipped portion) of "automated".


If you have a valid point to make, it's much better to simply make it.
No amount of sarcasm can replace it.

Dan
--
Dan Pop
DESY Zeuthen, RZ group
Email: Da*****@ifh.de
Nov 14 '05 #43
Damn Skippy <sk****@damn.invalid.org> wrote in message news:<tp********************************@4ax.com>. ..
On Mon, 01 Dec 2003 11:25:41 -0600, Ed Morton
<mo****************@lucent.com> wrote:
I'm not 100% against gotos, I've just never seen code that uses gotos
that I personally find more readable than the equivalent without gotos.
I recently wrote a short (200 lines or so) program using gotos just to
see if I could learn to appreciate the benefits wrt error-handling, but
once the error-handling became even moderatly complex (i.e. realisitc!)
the initial simplicity afforded by the gotos fell away. I looked at your
code hoping to learn a good way to use goto for readability.

Ed.
To me,

if ( a) { ... }

reads the same as

if (!a) goto skip_this; { ... } skip_this:

especially, and i will be flamed for this, if you consider the opcodes
which will be generated, on the actual real tangible machine(s) on
which it will run. When you think of it this way, it doesn't matter
whether you use goto or not, cos the CPU will (i.e. JUMP type of
instruction).


Most compilers are optimizing anyway, or at least become so with the
addition of options. gcc, for example, probably knows more about
opcode scheduling on Intel chips than I'll ever want or need to (how
to avoid cache misses, pairing rules, etc.), so I can trust it to
generate optimal code even if I give it human-readable C.

I think the impact of optimizing compilers plus the continuous
increases in chip speed negate the whole notion of manually optimizing
C in that way. If you need to speed things up, give the compiler a few
options. If you really need a speedup, choose a different algorithm.
As a last resort, hand-code some assembly.

So you must decide what is readable, and what other people will think
is readable. Bottom line - if people keep asking you why you have all
those 'goto' statements, it's time to cut back.
Of course, some people will flame you for having any goto statements.
Or break statements. Or subroutines with more than one return
statement. Or assignments. Or ... ;)

Remember, C code will be:
1) compiled and executed or
2) interpreted or
3) in a textbook, hopefully with rules and exceptions
That's probably true, but you still can trust the compiler farther
than you seem willing to.


============ inefficient, inelegant, recommended ===========
Inefficient is relative: If a Pentium burns a few thousand clock
cycles on inefficient assembly, what have I actually lost? Less than a
second.

Inelegant is also in the eye of the beholder: I think the code below
is perfectly readable.

for ( .. ) {
if ( a != b ) {
good=false;
complain();
break;
}
}

if (good) {
process();
}

cleanup_regardless:
This label isn't referenced by anything yet. I don't know if that's
warnable, but it certainly looks odd.
cleanup();

============ better? saves one test and one stack variable ===========
Maybe on some machines with some compiler options.

And it isn't very structured: What happens when you want to change the
behavior of the code, perhaps add a test for some edge case in some
instances, instead of simply jumping straght to cleanup_regardless
every time? With a subroutine, you simply add a value you can pass in.
With a goto, you either duplicate code to check for the edge case
everywhere that needs it right before the goto (a very poor solution),
you use a global you check at the point you jump to (another poor
solution), or you add another label in your code and modify goto
statements (a third poor substitute for good planning).

for ( .. ) {
if ( a != b ) {
complain();
goto cleanup_regardless;
}
}

process();

cleanup_regardless:
cleanup();

============ ===========

of course, i hope i never see gotos in something like:
I don't think anyone is here to condone that. I think there would be
more people willing to defend the ALTER verb in COBOL than that mess.

if ( (fp = fopen(szFilename)) != NULL ) {
if ( fread (&buf, 1, len, fp) == len ) {
if ( !strncmp ( buf, 4, "JFIF") ) {
process_jfif();
}
}
}

Nov 14 '05 #44
In article <br**********@sunnews.cern.ch>, Da*****@cern.ch says...
In <3F***************@yahoo.com> CBFalconer <cb********@yahoo.com> writes:
I think it is high time for you to take Richards refresher course
in Reading for Comprehension, after which you can consider the
"/reasonable/" and "regression test" above, and the implication
(from the snipped portion) of "automated".


If you have a valid point to make, it's much better to simply make it.
No amount of sarcasm can replace it.

Dan


No question, the use of terms and phrases such as "stupid", "idiot",
"engage your brain", "what a stupid poster", "are you so pathetically
stupid", "If you're so stupid that ...", "This is downright idiotic",
"moron", etc. are far better ways to make a point, right Dan?

--
Randy Howard _o
2reply remove FOOBAR \<,
______________________()/ ()______________________________________________
SCO Spam-magnet: po********@sco.com
Nov 14 '05 #45
In <MP************************@news.megapathdsl.net > Randy Howard <ra**********@FOOmegapathdslBAR.net> writes:
In article <br**********@sunnews.cern.ch>, Da*****@cern.ch says...
In <3F***************@yahoo.com> CBFalconer <cb********@yahoo.com> writes:
>I think it is high time for you to take Richards refresher course
>in Reading for Comprehension, after which you can consider the
>"/reasonable/" and "regression test" above, and the implication
>(from the snipped portion) of "automated".


If you have a valid point to make, it's much better to simply make it.
No amount of sarcasm can replace it.

Dan


No question, the use of terms and phrases such as "stupid", "idiot",
"engage your brain", "what a stupid poster", "are you so pathetically
stupid", "If you're so stupid that ...", "This is downright idiotic",
"moron", etc. are far better ways to make a point, right Dan?


I never use them *instead* of making a point, but in addition to it.

Dan
--
Dan Pop
DESY Zeuthen, RZ group
Email: Da*****@ifh.de
Nov 14 '05 #46

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

25
by: BOOGIEMAN | last post by:
I've just finished reading Python turtorial for non-programmers and I haven't found there anything about some usefull commands I used in QBasic. First of all, what's Python command equivalent to...
36
by: Michael | last post by:
Hi, I know I know its notoriously bad! I don't want to use it. I was wondering, does it still exist? If it does, I really don't understand how!? like what happens if you just goto halfway through...
5
by: deko | last post by:
I've heard it said that you only want to use a number (e.g. integer, long, etc.) if you are going to do calculations or some kind of math with it. Is this true? For example, I run a validate...
51
by: WindAndWaves | last post by:
Can anyone tell me what is wrong with the goto command. I noticed it is one of those NEVER USE. I can understand that it may lead to confusing code, but I often use it like this: is this...
17
by: Mike Hofer | last post by:
While I'd toyed with C, C++, and Java over the last 20 years or so, my principal language has been BASIC, QBASIC, then Visual Basic, and finally Visual Basic .NET. But lately, I've been using C#...
77
by: M.B | last post by:
Guys, Need some of your opinion on an oft beaten track We have an option of using "goto" in C language, but most testbooks (even K&R) advice against use of it. My personal experience was that...
8
by: cat | last post by:
I had a long and heated discussion with other developers on my team on when it makes sense to throw an exception and when to use an alternate solution. The .NET documentation recommends that an...
34
by: electrician | last post by:
Perl has it, Basic has it, Fortran has it. What is so difficult about creating a goto command for JavaScript. Just set up a label and say go to it.
59
by: raashid bhatt | last post by:
why are GOTO's not used they just a simple JMP instructions what's bad about them
0
by: Charles Arthur | last post by:
How do i turn on java script on a villaon, callus and itel keypad mobile phone
0
by: ryjfgjl | last post by:
In our work, we often receive Excel tables with data in the same format. If we want to analyze these data, it can be difficult to analyze them because the data is spread across multiple Excel files...
0
by: emmanuelkatto | last post by:
Hi All, I am Emmanuel katto from Uganda. I want to ask what challenges you've faced while migrating a website to cloud. Please let me know. Thanks! Emmanuel
1
by: Sonnysonu | last post by:
This is the data of csv file 1 2 3 1 2 3 1 2 3 1 2 3 2 3 2 3 3 the lengths should be different i have to store the data by column-wise with in the specific length. suppose the i have to...
0
marktang
by: marktang | last post by:
ONU (Optical Network Unit) is one of the key components for providing high-speed Internet services. Its primary function is to act as an endpoint device located at the user's premises. However,...
0
jinu1996
by: jinu1996 | last post by:
In today's digital age, having a compelling online presence is paramount for businesses aiming to thrive in a competitive landscape. At the heart of this digital strategy lies an intricately woven...
0
by: Hystou | last post by:
Overview: Windows 11 and 10 have less user interface control over operating system update behaviour than previous versions of Windows. In Windows 11 and 10, there is no way to turn off the Windows...
0
tracyyun
by: tracyyun | last post by:
Dear forum friends, With the development of smart home technology, a variety of wireless communication protocols have appeared on the market, such as Zigbee, Z-Wave, Wi-Fi, Bluetooth, etc. Each...
0
agi2029
by: agi2029 | last post by:
Let's talk about the concept of autonomous AI software engineers and no-code agents. These AIs are designed to manage the entire lifecycle of a software development project—planning, coding, testing,...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.