goto statement
-
Why many hate this statement and do not advise using it! I used it when I started programming with BASIC and GWBASIC. It is also found in the C#. Troubles are based on the programmer who is misusing it.
After far more than 20 years with C/C++ (and other languages too) I put it this way: I strongly recommend not using goto - except if it is really necessary. There should be no dogma but only good reasoning. There are good reasons for using a goto (most goto-s I've seen did not, but few did). In total I personally used it about maybe 10 times over all those years, but (as far as I see it) not breaking readability but guaranteeing readability at those perticular points. Of course it would have been possible to avoid the goto-s there too but only if I would have been breaking the "natural" logic of that code (or at least what seemed "natural" to me ;-)). Making a long talk short, I think: "There is no silver bullet".
-
OriginalGriff wrote:
it needs a careful look at the whole of what is occurring and frequently a change of algorithm as well as hand-tuning of the code
I've done some minor bits of optimization on occasion. I've never needed
goto
as part of any hand-tuning. Algorithm improvements and refactoring are generally the way to go for me.Software Zen:
delete this;
I second that. I've done lots of performance tuning, but it never required
goto
. At most, goto may improve the performance of the programmer who puts it into the code - but in the long run that "performance gain" will be lost in maintenance cost mmany times over! -
Under the hood almost every code block that is put into curly brackets is implemented with machine instructions for conditional or unconditional branches. GOTOs, if you want. They have just been hidden away. Unstructured spaghetti code is very hard to read and maintain. Readability and maintainability are even more important than correctness, at least in my book. Correctness will eventually follow as long as the code is readable. What I don't like is when people start religiously following rules and can even recite the reasons for them, often obviously without understanding the intentions behind them. 'Bad' code may have some other advantage than readability. If that advantage in a specific situation becomes more valuable than readability, then I would happily do what needs to be done. I also would heavily comment it to document my reasons for doing this. And the whole time I would enjoy the wailing of the code Nazis. :)
Sent from my BatComputer via HAL 9000 and M5
CDP1802 wrote:
Under the hood almost every code block that is put into curly brackets is implemented with machine instructions for conditional or unconditional branches. GOTOs, if you want. They have just been hidden away.
I first cut my teeth on ICL System4 mainframes in 1979 and can still remember the conditional/unconditional branch instruction's machine code - 47 xx yy yy (I think JMP was it's assembler code mnemonic). XX was the condition, 0F was an unconditional branch. And YY YY was the prog address to go to. :) It's scary some of the completely useless info your brain retains.
If your neighbours don't listen to The Ramones, turn it up real loud so they can. “We didn't have a positive song until we wrote 'Now I Wanna Sniff Some Glue!'” ― Dee Dee Ramone "The Democrats want my guns and the Republicans want my porno mags and I ain't giving up either" - Joey Ramone
-
If you know what you are doing, then you have enough experience to know when it is appropriate to use. I completely agree with you: it's a useful tool. But like all tools, you have to know how and when to use it. Performance tuning (as you know well) needs more than just "quick code" - it needs a careful look at the whole of what is occurring and frequently a change of algorithm as well as hand-tuning of the code. And if you know what you are doing enough to do that, you understand the effects of your changes. Even Dijkstra said that it has it's place, but that use must be tempered with knowledge of the effects. Obligatory XKCD reference[^]
The only instant messaging I do involves my middle finger. English doesn't borrow from other languages. English follows other languages down dark alleys, knocks them over and goes through their pockets for loose grammar.
Another big consideration is use of goto's will frequently severely hamper of the ability of your compiler to optimise code - without the application knowledge, it can rarely make safe assumptions in their presence and it messes up the SSA (Static Single Assignment) style optimisations by complicating the control flow graph. So while you may be able to think of it at as optimisation, it may prevent the compiler doing so. It's also not high on the list of things they feel they should concentrate on, so I wouldn't count on big improvements soon.
"If you don't fail at least 90 percent of the time, you're not aiming high enough." Alan Kay.
-
After using FORTRAN for far too long (up to Fortran-77) with it's use of GOTO and, even more obfuscating, computed gotos, I started using C. However, I was self-taught and was therefore never was taught by anybody that there was a GOTO in the language! I used C for several years, then C++ and now I am firmly in the C# camp. I personally have never used GOTO in any of that code and was shocked one day to find a GOTO residing in someone else's code I had to fix. It was a revelation as big as finding out that one is allowed to use guns during a penalty kick-off. I didn't even know the syntax existed! The whole point of my argument is that I never felt the need for a GOTO at any time, ever - so I didn't miss it. I didn't make artificial constructs to get around using GOTO; I didn't deliberately re-write my code to avoid using one; it just came about naturally that I didn't ever need one. Having said that, I am sure that GOTO may be useful in some real-time code somewhere for performance reasons. My real bug-bear is with multiple RETURNs. I do actually go out of my way to avoid them and re-write them out of existence wherever I find them. I have not yet found any instance where multiple RETURNs from a method has been necessary. I miss allowing the drop through of CASE statements in a switch that has been removed in C#, forcing me to put BREAK at the end of each part and leading me to repeat code unnecessarily now and then so I am not always in favour of compiler/syntax restrictions in a language but I wish multiple RETURNs had been proscribed in the same way.
- I would love to change the world, but they won’t give me the source code.
I think that multiple return advice is not longer necessary in modern C++ - simply use RAII style techniques, and you are guaranteed correct cleanup at exit. (Still shouldn't be overrused though)
"If you don't fail at least 90 percent of the time, you're not aiming high enough." Alan Kay.
-
That code is you showed is fine, and I also prefer the the nested form of error checking when it is manageable. That isn't always the case. (Note the comment in my last message, there is no "silver bullet!") As I wrote in my code example, "That construct avoids the extreme indenting that can occur with a lot of nested error checks." The key words are "can" and "nesting". Deep nesting cannot always be easily avoided by breaking into functions, and when that is the case, the loop construct is useful. For the example below I used the nested form to compare 8 keys, where the values of the 8 keys form a single key to a dictionary (or a map). Each item in the map is sorted in lexicographic order. (This code snippet is taken from the article Generic Sparse Array and Sparse Matrices in C#[^]
public int CompareTo(ComparableTuple8 group) { int result = this.Item0.CompareTo(group.Item0); if (result == 0) { result = this.Item1.CompareTo(group.Item1); if (result == 0) { result = this.Item2.CompareTo(group.Item2); if (result == 0) { result = this.Item3.CompareTo(group.Item3); if (result == 0) { result = this.Item4.CompareTo(group.Item4); if (result == 0) { result = this.Item5.CompareTo(group.Item5); if (result == 0) { result = this.Item6.CompareTo(group.Item6); if (result == 0) { result = this.Item7.CompareTo(group.Item7); } } } } } } } return result; } #endregion }
That is 8 keys.
Examples like this really make the advantages of C++'s templates apparent. That could all be done by recursion - evaluated at compile-time, and be generalised to any N-tuple. It also makes the advantage of RAII apparent - use multiple returns safely with the guarantee of deterministic cleanup.
"If you don't fail at least 90 percent of the time, you're not aiming high enough." Alan Kay.
-
Why many hate this statement and do not advise using it! I used it when I started programming with BASIC and GWBASIC. It is also found in the C#. Troubles are based on the programmer who is misusing it.
1. If it is critical that your code is correct, don't use
goto
: it has the capability to jump out of or into one or more nesting layers - even backwards - and thus makes it considerably harder to verify the correctness of the code. 2. If there is more than one programmer on the team, don't usegoto
: using it makes it considerably harder for another programmer to understand the flow of code, and what it is supposed to do. 3. If you intend to build on and maintain the code over a period of more than a couple of months, don't usegoto
: viewing a piece of code that you yourself wrote a couple of months ago is often not so much different from viewing another programmers' code - see item 2 above. Please note that modern programming languages have plenty of alternatives that can be used in many cases where goto could be used. In C/C++, here are some examples: - to repeat a block of code, use afor
,while
, ordo
loop construct rather than jumping backwards - to skip over some piece of code, use anif
-block rather than jumping forward - to skip over the rest of a loop body, usecontinue
- to exit out of a loop, usebreak
In C++ you should also use the standard exception handling mechanism rather than usinggoto
as an error exit mechanism. (There is no equivalent in C, so you might argue that in C the use ofgoto
for that purpose is acceptable - but see below!) The main reason however that you shouldn't usegoto
is that there is no benefit. Over the past 30 years I've used, learned about, read about, and had plenty of discussions aboutgoto
. In all that time I've never heard or read one compelling argument in favor of using it. Yes, you can use it to reduce or avoid nesting, or otherwise reduce the amount of code. But that by itself is not a valid argument in my book. -
It's right there in C++ as well....
If your neighbours don't listen to The Ramones, turn it up real loud so they can. “We didn't have a positive song until we wrote 'Now I Wanna Sniff Some Glue!'” ― Dee Dee Ramone "The Democrats want my guns and the Republicans want my porno mags and I ain't giving up either" - Joey Ramone
... for backward compatibility only.
-
Why many hate this statement and do not advise using it! I used it when I started programming with BASIC and GWBASIC. It is also found in the C#. Troubles are based on the programmer who is misusing it.
-
Why many hate this statement and do not advise using it! I used it when I started programming with BASIC and GWBASIC. It is also found in the C#. Troubles are based on the programmer who is misusing it.
-
Why many hate this statement and do not advise using it! I used it when I started programming with BASIC and GWBASIC. It is also found in the C#. Troubles are based on the programmer who is misusing it.
Most of the first and second-generation languages were conceptually founded on some problem-oriented model. In focusing on a particular problem space, they tended to neglect other considerations. One result was that many languages were merely "assembler with better syntax" -- and the GOTO or branch instruction is impossible to do without in that scheme.
Third-generation languages such as Algol and C began the move away from a hard problem orientation. They focused on other desiderata, such as structure and legibility. With the expansion in the variety of conditional and iterative control structures they offered, the GOTO became less necessary. That caused Dijkstra and others to study the relation between the GOTO and legible / comprehensible program design, and to reach the conclusion that the GOTO is harmful in the great majority of cases.
All that having been said, there are still occasions when writing a GOTO is better practice than what it would take to avoid it. Indeed, some such cases involve using a GOTO to improve legibility and maintainability; transfer of control to a procedure's error handling exit is sometimes like that. However, it's best to be biased against GOTO, and to use it reluctantly, because GOTOs are a bit like wire coat hangers: they tend to breed in the darkness, such that where there once were few, eventually there are many, and the program's architecture collapses beneath them.
(This message is programming you in ways you cannot detect. Be afraid.)
-
I use it and feel good when it is in my code because so many reputable sources are saying "do not do it" but not really showing any good reason why it is bad.
It's often hard to understand the reasons if all you do is look at the code you've just written. You have to "look" at the code that it will grow into after a year or more of maintaining and extending that code however! I've seen some huge 15-20 year old functions with several hundreds or even thousands of lines of code. After so many years, I could still guess the general shape and design of these functions when they were first written, and at that time, using goto was neither looked down upon quite as much, nor did it seem unreasonable in that particular piece of code. Over the years however, tons of features were added who required additional blocks of code; dozens of corner cases were detected that needed to be treated separately; and at least half a dozen developers added their differing visions of how the code should be formatted and designed. One of the things I tried over the years is split up that code into smaller, better maintainable chunks, but I've found there is no easy way to ensure this won't break the multitude of corner cases handled by this code. I could move some of it into initialization functions, and extract a few of the special feature code blocks. But it was nigh impossible to disentangle the mass of conditional code and goto statements (few as there were) while ensuring that the code would behave exactly like it did before. With none of the original programmers around to help determine what exactly the code was supposed to do, breaking it was too high a risk to take. I'm not saying that the
goto
statements were the sole reason for the sorry, unmaintainable state of the code, but they were the main reason why I was unable to transform it into something maintainable! tl;dr: If all you do is write short lived functions and programs then use goto at your hearts desire. But if that code that you're writing will go into a professional application that may live on and be maintained and exxtended for many years, then you better think ahead and don't introduce a legacy that is hard to bear and harder to kill! -
Most of the first and second-generation languages were conceptually founded on some problem-oriented model. In focusing on a particular problem space, they tended to neglect other considerations. One result was that many languages were merely "assembler with better syntax" -- and the GOTO or branch instruction is impossible to do without in that scheme.
Third-generation languages such as Algol and C began the move away from a hard problem orientation. They focused on other desiderata, such as structure and legibility. With the expansion in the variety of conditional and iterative control structures they offered, the GOTO became less necessary. That caused Dijkstra and others to study the relation between the GOTO and legible / comprehensible program design, and to reach the conclusion that the GOTO is harmful in the great majority of cases.
All that having been said, there are still occasions when writing a GOTO is better practice than what it would take to avoid it. Indeed, some such cases involve using a GOTO to improve legibility and maintainability; transfer of control to a procedure's error handling exit is sometimes like that. However, it's best to be biased against GOTO, and to use it reluctantly, because GOTOs are a bit like wire coat hangers: they tend to breed in the darkness, such that where there once were few, eventually there are many, and the program's architecture collapses beneath them.
(This message is programming you in ways you cannot detect. Be afraid.)
Fran Porretto wrote:
GOTOs are a bit like wire coat hangers: they tend to breed in the darkness, such that where there once were few, eventually there are many, and the program's architecture collapses beneath them.
Ooooh, I like that! Can I use it in my sig? ;)
-
Fran Porretto wrote:
GOTOs are a bit like wire coat hangers: they tend to breed in the darkness, such that where there once were few, eventually there are many, and the program's architecture collapses beneath them.
Ooooh, I like that! Can I use it in my sig? ;)
(chuckle) Feel free. It was spontaneous, but the more I ponder it, the more accurate it seems!
(This message is programming you in ways you cannot detect. Be afraid.)
-
Why many hate this statement and do not advise using it! I used it when I started programming with BASIC and GWBASIC. It is also found in the C#. Troubles are based on the programmer who is misusing it.
Yes, I can agree that the goto statement can be confusing and I've never found a good use for it. However what is the difference between a goto and a exceptions? Exceptions are only suppose to be used for things that should never happen. Most of the time that I've seen them used for all error-handling methods. (E.G. Invalid user input) However I find throwing exceptions for this purpose, even with the performance hit, useful. It keeps the code cleaner and shows the next guy what I expect to happen. Just wondering what you thought? P.S. I once worked in a 4k memory space divided into 2 sections. The only way to get to the second memory space was with a goto statement.
-
Because in nearly every case I have seen of it's use in C# or C++ it has been unnecessary, and only served to both confuse the code and show that the person who used it did not understand what he was doing.
goto
is not evil - but it is a "rule breaker" in that it violates all the principles of good code design and so using it should only be done with care. The problem is that it it taught on courses by lazy tutors as an easy way to get them started and then gets abused later because the students consider it "Normal" and don't learn to structure code well in the first place as a result. If you had grown up withGOTO
as pretty much the only form of flow control (as I did) you would probably understand how easy it is to create impenetrable code with it, and why it should be discouraged until the coder is experienced enough to know when it is appropriate. About five years of "real" coding should be enough. But by then, he is probably experienced enough to know that there are probably better ways to achieve the same result...The only instant messaging I do involves my middle finger. English doesn't borrow from other languages. English follows other languages down dark alleys, knocks them over and goes through their pockets for loose grammar.
"Clever" use of GOTO can create macramé like code that is impossible to debug.
I may not last forever but the mess I leave behind certainly will.
-
Examples like this really make the advantages of C++'s templates apparent. That could all be done by recursion - evaluated at compile-time, and be generalised to any N-tuple. It also makes the advantage of RAII apparent - use multiple returns safely with the guarantee of deterministic cleanup.
"If you don't fail at least 90 percent of the time, you're not aiming high enough." Alan Kay.
This is C# code, (although I have a SparseArray template for C++ article on codeproject). This code does look just like C++ though. The code was generated by a program. I had to create ComparableTuple generics for so many sizes, I wrote a program that generates the code. Still, I would want the code to be readable afterward. If you meant the code generator could use recursion, I agree, although the code I wrote uses iteration. I expect that is almost certainly what you meant. The run-time code shouldn't use recursion as that would be too inefficient, and this needs to be as fast as possible.
-
Why many hate this statement and do not advise using it! I used it when I started programming with BASIC and GWBASIC. It is also found in the C#. Troubles are based on the programmer who is misusing it.
In 1974, my manager asked me to evaluate the new, highly touted discipline called "structured programming." I was skeptical. At that time, I was programming in COBOL. In those days, COBOL was somewhat deficient in the amount of control structures provided. I had not yet read Bohm and Jacopini so I had no idea that the control structures of COBOL were more than adequate for the task. I suggested that I wait to perform a structured programming experiment until a new project came along. In July, I was assigned a new project. The Chief of Naval Operations (CNO) Budget Office was in need of a text editor that could edit the descriptive portions of records in an indexed sequential file. The program would be developed and executed on a Unisys 1106 main frame computer. Unfortunately, the Budget Office also knew about the University of Maryland Text Editor (med) which, for all intents and purposes, replaced the Unisys provided editor (ed). The Budget Office wanted the interface to be "just like med" a seemingly impossible job for the short project time (three months). Fortunately, I found that med contained an API that would allow me to use the editor against the textual fields of the indexed sequential file. So it began. For this project I could not use a GOTO statement, a standard tool of the COBOL programmer of those days. I struggled with the problem. It wasn't that the solution was difficult; the solution was difficult without using GOTOs. Finally, in September, I finished. When queried by my manager, I told him that the programming effort took longer than it would have had I not used the structured programming paradigm. We agreed that, even though some rather impressive academians had suggested that structured programming was the way to go, we would shelve further use of the method. I placed the code listing in one of the drawers of my desk and returned to programming in my normal unstructured way. Then, in December, I received a call from the CNO production office. It appeared that a program that I had written had blown up. The production office provided the symptoms and the name of the program. I looked in my drawer and found the flawed program. When I opened the listing, I realized that this was the program that I had struggled with. As I reviewed the code, in light of the comments provided by the production office, the bug just seemed to jump from the page. It was such a simple error. But had I written the code in my normal manner, I would never have found the problem so quickly. After about fifte
-
If you know what you are doing, then you have enough experience to know when it is appropriate to use. I completely agree with you: it's a useful tool. But like all tools, you have to know how and when to use it. Performance tuning (as you know well) needs more than just "quick code" - it needs a careful look at the whole of what is occurring and frequently a change of algorithm as well as hand-tuning of the code. And if you know what you are doing enough to do that, you understand the effects of your changes. Even Dijkstra said that it has it's place, but that use must be tempered with knowledge of the effects. Obligatory XKCD reference[^]
The only instant messaging I do involves my middle finger. English doesn't borrow from other languages. English follows other languages down dark alleys, knocks them over and goes through their pockets for loose grammar.
OriginalGriff wrote:
If you know what you are doing, then you have enough experience to know when it is appropriate to use.
Yeah, but how do you know when you have enough experience to know when it's appropriate to use? :laugh: And then there's my sig...
If you think 'goto' is evil, try writing an Assembly program without JMP.
-
Why many hate this statement and do not advise using it! I used it when I started programming with BASIC and GWBASIC. It is also found in the C#. Troubles are based on the programmer who is misusing it.
Because they are ignorant idiots. Goto is absolutely essential in a number of cases. Most notable are: - Implementing state machines. The closest construction to state transition is goto, so it must be expressed as goto. - Various generated code (from higher level languages/DSLs)