473,785 Members | 2,468 Online
Bytes | Software Development & Data Engineering Community
+ Post

Home Posts Topics Members FAQ

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
45 2729
"Michael B." <us*****@spambl ocked.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_regardl ess:
cleanup();

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

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

process();

cleanup_regardl ess:
cleanup();

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

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

if ( (fp = fopen(szFilenam e)) != 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_regardl ess:
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_regardl ess;
}
}

process();

cleanup_regardl ess:
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(szFilenam e)) != 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********@yah oo.com> wrote in message news:<3F******* *******@yahoo.c om>...
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********@yah oo.com> wrote in message news:<3F******* *******@yahoo.c om>...
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********@yah oo.com> wrote in message news:<3F******* *******@yahoo.c om>...
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

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

Similar topics

25
4652
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 QBasic's "goto" ? Secondly, how do I clear screen (cls) from text and other content ? And last, how do I put program to wait certain amount of seconds ? If I remeber correctly I used to type "Wait 10" and QBasic waits 10 seconds before proceeding...
36
6740
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 a function (no objects properly constructed!) , or a constructor itself?? Just intrigued!! Mike
5
1795
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 routine that checks an address entry - if something's missing in the entry, the code does different things based on what is missing, indicated my a 2 or a 3 - integer values. Should I use string data types here? Does it matter? Public Sub...
51
13388
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 wrong????? Function x select case z
17
2319
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# and I absolutely *love* it. It makes me think more about what I'm doing it before I just spew code into the editor. I'm writing better code than ever. The only thing so far that I don't like about it is the switch construct. I can't do this:
77
4040
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 goto sometimes makes program some more cleaner and easy to understand and also quite useful (in error handling cases). So why goto is outlawed from civilized c programmers community. is there any technical inefficiency in that.
8
2259
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 exception should be thrown only in exceptional situations. It turned out that each of my colleagues had their own interpretation about what an "exceptional situation" may actually be. First of all, myself I’m against using exceptions extensively,...
34
26648
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
5066
by: raashid bhatt | last post by:
why are GOTO's not used they just a simple JMP instructions what's bad about them
0
9491
by: Hystou | last post by:
Most computers default to English, but sometimes we require a different language, especially when relocating. Forgot to request a specific language before your computer shipped? No problem! You can effortlessly switch the default language on Windows 10 without reinstalling. I'll walk you through it. First, let's disable language synchronization. With a Microsoft account, language settings sync across devices. To prevent any complications,...
0
10357
Oralloy
by: Oralloy | last post by:
Hello folks, I am unable to find appropriate documentation on the type promotion of bit-fields when using the generalised comparison operator "<=>". The problem is that using the GNU compilers, it seems that the internal comparison operator "<=>" tries to promote arguments from unsigned to signed. This is as boiled down as I can make it. Here is my compilation command: g++-12 -std=c++20 -Wnarrowing bit_field.cpp Here is the code in...
0
9959
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 protocol has its own unique characteristics and advantages, but as a user who is planning to build a smart home system, I am a bit confused by the choice of these technologies. I'm particularly interested in Zigbee because I've heard it does some...
1
7510
isladogs
by: isladogs | last post by:
The next Access Europe User Group meeting will be on Wednesday 1 May 2024 starting at 18:00 UK time (6PM UTC+1) and finishing by 19:30 (7.30PM). In this session, we are pleased to welcome a new presenter, Adolph Dupré who will be discussing some powerful techniques for using class modules. He will explain when you may want to use classes instead of User Defined Types (UDT). For example, to manage the data in unbound forms. Adolph will...
0
6744
by: conductexam | last post by:
I have .net C# application in which I am extracting data from word file and save it in database particularly. To store word all data as it is I am converting the whole word file firstly in HTML and then checking html paragraph one by one. At the time of converting from word file to html my equations which are in the word document file was convert into image. Globals.ThisAddIn.Application.ActiveDocument.Select();...
0
5397
by: TSSRALBI | last post by:
Hello I'm a network technician in training and I need your help. I am currently learning how to create and manage the different types of VPNs and I have a question about LAN-to-LAN VPNs. The last exercise I practiced was to create a LAN-to-LAN VPN between two Pfsense firewalls, by using IPSEC protocols. I succeeded, with both firewalls in the same network. But I'm wondering if it's possible to do the same thing, with 2 Pfsense firewalls...
0
5532
by: adsilva | last post by:
A Windows Forms form does not have the event Unload, like VB6. What one acts like?
1
4063
by: 6302768590 | last post by:
Hai team i want code for transfer the data from one system to another through IP address by using C# our system has to for every 5mins then we have to update the data what the data is updated we have to send another system
3
2894
bsmnconsultancy
by: bsmnconsultancy | last post by:
In today's digital era, a well-designed website is crucial for businesses looking to succeed. Whether you're a small business owner or a large corporation in Toronto, having a strong online presence can significantly impact your brand's success. BSMN Consultancy, a leader in Website Development in Toronto offers valuable insights into creating effective websites that not only look great but also perform exceptionally well. In this comprehensive...

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.