5 ms·
They don't really mention it in the style guideline but there are two primary reasons for using goto in C and they're to make up for two other language deficien
by Locke1689 15y ago
They don't really mention it in the style guideline but there are two primary reasons for using goto in C and they're to make up for two other language deficiencies.
The first is the lack of exceptions. This is not necessarily a deficiency in kernel code because it can make other code more complex, but fundamentally error handling and cleanup usually either requires 1) keeping track of a bunch of state and then using complicated logic to evaluate the state for error cases 2) exception catching such that error conditions can be thrown up, caught, and brought to a cohesive resolution or 3) goto, such that cohesive cleanup code can be placed together in a segment and then jumped to on error conditions. (3) is far superior to (1) and, while (2) is arguably superior to (3), it simply doesn't exist in C.
The second case is that C doesn't have a multi-level break. That is, when in multiple nested blocks (loops), in order to exit early one would have to keep track of state and use conditionals to trigger a "waterfall" break all the way down the block chain. goto solves this by allowing you to jump out of the chain completely. I think most people would probably agree that adding a multilevel break (e.g., "break 2;") would probably be preferable to using goto here, but I think the workaround is basic enough (either use goto or refactor into separate functions) that the language addition is unlikely now.
- Symmetry 15y agoOne additional use, which I ran into a few years ago, is to make it explicit when you're falling through in a case statement.
- kristopolous 15y agoI'd like to see an example. Are you familiar with Duff's Device btw?
- Symmetry 15y agoAn example then: switch( machineState ){ case ALPHA: ... break; case BETA: ... goto location; case GAMMA: location: ... } No, I wasn't familiar with Duff's device until just now. I'd say that you only need to be explicit about pointing out fallthroughs if the blocks in the switch statements are more than a couple of lines long.
- tspiteri 15y agoI find that use of goto quite confusing, and would prefer a comment in such a case: switch( machineState ){ case ALPHA: ... break; case BETA: ... /* fallthrough */ case GAMMA: ... }
- JadeNB 15y agoThat's particular to situations that can be solved by fallthrough. What about switch ( machineState ) { case ALPHA: ... alpha prep ... goto gamma case BETA: ... beta prep ... goto gamma case GAMMA: gamma: ... } ? (EDIT: Not to say that you shouldn't still comment, of course.)
- nitrogen 15y agoIn this case it might be clearer to just run the switch again after ALPHA and BETA with GAMMA as the machineState, and if necessary, have logic in GAMMA for switching machineState back to ALPHA or BETA. It also might be clearer to move GAMMA outside the switch block entirely: int shouldGamma = 0; switch ( machineState ) { case ALPHA: ... alpha prep ... shouldGamma = 1; break; case BETA: ... beta prep ... shouldGamma = 1; break; case GAMMA: shouldGamma = 1; break; } if(shouldGamma) { // GAMMA stuff here } The shouldGamma flag would be unnecessary if all possible values for machineState should still run the code in GAMMA.