Join 300,428 Programmers for FREE! Get instant access to thousands of experts, tutorials, code snippets, and more! There are 1,484 people online right now. Registration is fast and FREE... Join Now!
The GOTO statements mostly were used before the actual introduction of structural programming. Those generate the so-called 'spaghetti-code', which makes it harder to read and understand. Statistics show, that sometimes there is no performance loss if using GOTO statements, however, it is still recommended to use loops and if-else statements instead.
After a while even the original programmer could get lost in their own code.
Think about it like giving driving directions. I'm going to tell you how to get to my house:
1. Back out of your driveway 2. GOTO 9 3. Turn left 4. GOTO 8 5. Take the exit ramp 6. GOTO 9 7. Arrive 8. Merge onto the interstate 9. Go the stop sign
The above is a mess, it isn't logical in any regard, doing this is better:
1. Back out of your driveway 2. Go the stop sign 3. Turn left 4. Merge onto the interstate 5. Take the exit ramp 6. Go the stop sign 7. Arrive
The idea that the goto statement somehow leads to "spaghetti code" is laughable. Careless programmers can easily create infinite loops that lock up their programs, should we stop using loops as well? The same can be said about virtually any programming construct.
Not every piece of code needs to be a work of art. I don't think there is a situation where using a goto statement is 100% necessary, but sometimes they can be convenient.
My teacher taught me that you have to do so much with Goto statements, they become very confusing(like the others previously stated). Also, one mess up, and you must go back into the whole code to find the problem. If you are making a program to distribute to others, Goto is definitely not for that reason.
The big problems with goto are readability and maintainability. Basically the excessive use of goto results in hard to find errors -- errors that are usually really STUPIDLY simple to fix but are really hard to track down. Using structured program lets the compiler worry about where all of the jumps go and frees you up from maintaining jump points.
There is also something to be said for the logic of it. Generally it is new programmers who like to use goto (I was one) but as you mature as a programmer you find the the control structures are more convenient and more logical. Code is written in a Language -- it should communicate its meaning -- goto is a command to the "reader" and really does not have anything to do with actual logic of the program (most of the time).
I have yet to see a situation that requires a goto in a procedural language
I will go so far as to say that there is never a situation where a goto offers any advantage in a structured language. I issued this challenge the last time the came up with no takers: please show me were a goto is an improvement and explain why.
Here's a decent write up on why a GOTO statement can be handy. While I personally don't agree with it, I think GOTO's should be avoided at all costs, this author does make a decent argument
When I started programming I used to think I 'needed' to use GOTOs all the time, when in reality if sat back and thought about the problem all it took was a different approach. Sometimes just doing that lead to a more creative yet simpler solution. I'm not saying GOTOs are useless, I'm just saying that there's more than one way to skin a cat (personally I think GOTOs are the 'chainsaw' approach to that problem - the cat gets skinned but it isn't pretty)
My school teacher would cancel pages of a program for a single use of goto.. pretty cruel... yet i have come to realize it can be terrible for large programs
Ever had a assembly language class??? Debugging assembly codes are painful as you will be jumping back and forth within some range of lines... because it uses couple of "jump" (GOTO) to create one if-else or while-loop.
It could be convenience in some case, but learn to use loop instead isn't too hard, why bother GOTO so much and argue with others saying GOTO is better in some case? Change a little bit, use loops, and problems(arguing with veteran) solved.
This post has been edited by mattsmee: 11 Mar, 2009 - 03:09 AM
Here's a decent write up on why a GOTO statement can be handy. While I personally don't agree with it, I think GOTO's should be avoided at all costs, this author does make a decent argument
Hadn't spotted this before, thanks. I don't agree either.
There are two places I use goto, ASM and T-SQL. For T-SQL the pattern looks pretty much like the author's rationale. However, the author has more flow control in C++ than in more sparse languages where a jump is the only option, so the affirmative argument seems dubious.
One approach would simply be a continue type flag. I quite dislike the constant calling to setMessage, so I fixed it in this one:
if (C_OpenSession(m_SlotID, &session) == CR_OK) { if (C_Login(session, pin.c_str(), pin.length()) == CR_OK) { logged_in = true; done = false; } else { returnval.setMessage("Couldn't log into the token"); } } else { returnval.setMessage("Couldn't open a session with the token"); }
if (done = (!done && C_FindObjectsInit(session, CKO_RSA_KEY) != CKR_OK)) { returnval.setMessage("Couldn't find any RSA keys on the token"); }
if (done = (!done && (C_FindObjects(session, NULL_PTR, &count) != CKR_OK || count < 1))) { returnval.setMessage("Couldn't find any RSA keys on the token"); }
if (done = (!done && !(key_handle = new CK_KEY[count]))) { returnval.setMessage("A memory allocation error occurred."); }
if (done = (!done && C_FindObjects(session, key_handle, &count) != CKR_OK) ) { returnval.setMessage("Couldn't retrieve RSA keys from the token"); }
// Much more code follows, each command having a single // short-circuit point that jumps to a single cleanup // section. There is only one function return path.
if (!done) { returnval = status::SUCCESS; returnval.setMessage("SUCCESS"); }
if (key_handle) delete [] key_handle; if (logged_in) C_Logout(session); return returnval; }
Another approach is one I use more in PL/SQL but have also applied to T-SQL and even C# and that's the have a try catch block where exceptions are raised to halt progression. Java has this sort of thing in their system libraries.
However, no matter what language you use, you should always take advantage of the strengths of the environment. An object that simply holds state is a practical solution. It's also a common one.
cpp
// state // holds data that needs to be passed back from login processing. struct LoginType { string pin; status returnval; CK_SESSION_HANDLE session; CK_KEY_HANDLE key_handle; bool logged_in = false; }
// the code that was is supposed to prove a case for goto elegance // here taken nearly verbatim, using a object and a void return void processLogin(LoginType &login) { CK_RV status; CK_ULONG count;
// open a session with the smart token login.returnval.setMessage("Couldn't open a session with the token"); status = C_OpenSession(m_SlotID, &login.session); if (status != CR_OK) { return; }
// login to the token returnval.setMessage("Couldn't log into the token"); status = C_Login(login.session, login.pin.c_str(), login.pin.length()); if (status != CR_OK) { return; } login.logged_in = true;
// initialize key search for all RSA keys on token login.returnval.setMessage("Couldn't find any RSA keys on the token"); status = C_FindObjectsInit(login.session, CKO_RSA_KEY); if (status != CKR_OK) { return; }
// determine how much space is need to retrieve all RSA keys login.returnval.setMessage("Couldn't find any RSA keys on the token"); status = C_FindObjects(login.session, NULL_PTR, &count); if (status != CKR_OK || count < 1) { return; }
// allocate memory to hold all keys login.returnval.setMessage("A memory allocation error occurred."); login.key_handle = new CK_KEY[count]; if (!login.key_handle) { return; }
// retrieve keys login.returnval.setMessage("Couldn't retrieve RSA keys from the token"); status = C_FindObjects(login.session, login.key_handle, &count); if (status != CKR_OK) { return; }
// Much more code follows, each command having a single // short-circuit point that jumps to a single cleanup // section. There is only one function return path.
// call the process status smart_token::login(string pin) { LoginType info = {pin, status::FAILED, NULL_PTR, NULL_PTR, false}; processLogin(info); // cleanup if (info.key_handle) delete [] info.key_handle; if (info.logged_in) C_Logout(info.session); return info.returnval; }
This is could been a lot cleaner if LoginType was a class and did some of the work for us. However, as it stands, it seems to be an equivalent solution with no nasty gotos.
I'm still waiting for an example where goto offers a significant enough advantage to warrant it's use. IMHO, this ain't it... next!
a nice discussion about goto statements with the famous Dijskstra and his letter about the abolishment of goto's as a starting point.
Part 1 and 2 is lots of text, but Part 3 gives a nice discussion about about two major programming problems, loop exiting and error handling, traditionally solved with goto's, and how one can tackle them today using more modern flow control.
To answer your question, GOTO's are absolutely fine and quite handy.
Don't use them unless its necessary and when necessary be careful.
When languages compile to Assembly Code things like switch statements, if statements and things of that nature compile to JMP commands which is in essence a GOTO.
When I started programming I used to think I 'needed' to use GOTOs all the time, when in reality if sat back and thought about the problem all it took was a different approach. Sometimes just doing that lead to a more creative yet simpler solution. I'm not saying GOTOs are useless, I'm just saying that there's more than one way to skin a cat (personally I think GOTOs are the 'chainsaw' approach to that problem - the cat gets skinned but it isn't pretty)
I thought goto was eliminated from most contemporarY high level languages. Is it still out there? And how the hell does one use it without line numbers?
I thought only the retro style BASIC languages -- like DARK BASIC and the old apple iie built in basic, etc. had that command.