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/
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();
}
}
}
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.
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
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
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.
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.
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
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
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 This thread has been closed and replies have been disabled. Please start a new discussion. Similar topics |
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...
|
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
|
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...
|
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
|
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:
| |
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.
|
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,...
|
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.
|
by: raashid bhatt |
last post by:
why are GOTO's not used they just a simple JMP instructions what's bad
about them
|
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,...
|
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...
| |
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...
|
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...
|
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();...
|
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...
|
by: adsilva |
last post by:
A Windows Forms form does not have the event Unload, like VB6. What one acts like?
|
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
| |
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...
| |