I was a professional C++ programmer as recently as 2024. The goto’s are forbidden “rule” is common knowledge but it’s wrong. goto’s became frowned upon with the advent of block-structured languages in the 1960’s for a reason, and people today forget the reason–they usually made code unclear and hard to maintain. The correct rule (my opinion of course) is use a goto when doing so improves clarity. For example, in C/C++ to exit nested loops, where a break statement only exits the innermost loop, a goto often improves clarity. Use it. Do not be afraid.
As far I know goto’s in C are good only in the local nested local block.
“if (bad input) GOTO restart-state-machine” is the kind of error handling I was thinking of.
The restrictions on goto statements in C are not as strong as you seem to think. If you have a state machine implemented as a big switch statement you can do a goto to the top level of the function that contains it. If you are in a small function called from the state machine, you are correct that you cannot “goto” a label in a different function. But you can have the small function return an error value, check for it in the switch statement, and then do a goto to the “top” and reinitialize the state machine. Or or you can use setjmp and longjmp to achieve your goal directly.
Ah yes, I was just thinking of mentioning that - I don’t think I’ve personally used it, but I think I’ve seen it done. It seems like powerful magic, but if you have the right view of how the stack gets used, I think it’s not too magical. I daresay one could get memory leaks though, depending on what kinds of data structures are in play.
Powerful magic, indeed…
I have this Basic Interpreter written in C.
It capable of allowing Basic program functions and procedures to call themselves recursively. To accomplish this the interpreter simply calls itself recursively.
Maybe you can guess where this is going…
So, deep inside some recursive Basic program an error happens. Say divide by Zero or something that gets caught by the interpreter run-time.
In my “holier than thou” quest to avoid GOTO, I flag the error then the C program executes ‘return’. This would return to the command-line of the interpreter or the function that called itself recursively… So it sees the error flag and executes a ‘return’ and so on until the stack (of the C program) is unwound.
I’m not going to say this is elegant or even clever (it’s brute-force) and there is a note in there to the effect of “Ye Ghods, Use longjmp next time!”.
Which would, I suspect be more elegant and possibly speed up execution of well behaved programs as it’s one less check to make.
One day I’ll do it, but to get out of the spiral death trap of deep recursion setjmp/longjmp would be an elegant solution in this instance IMO.
-Gordon
I used both methods to reduce code size in my 6502 port of the VTL-2 interpreter, and I have zero regrets, because small code size was my primary goal. Of course, I was helped greatly by the fact that all program syntax, logic, and execution errors are “undefined behavior” in the language specification itself. ![]()
May be more elegant, but as Ed points out, if you have any pointers to allocated memory in the stack, they are gone and the allocated memory will never be freed. For that you need a modern language with something like try/catch/finally. Or you could build some kind of garbage collection system but usually these things are orders of magnitude more complicated.
At least C2Y (C26?) is now apparently due to have labelled breaks.
In my case - a Basic interpreter written in C, then no - no data structures allocated on the stack, no garbage collection. And an inspection of the code last night suggests it will just work…
I just need to find some time to implement and test it, although the speed gain, if any, will be minimal. It’ll just save a few lines of code.
-Gordon