For larger switch case statements, is it better to separate them? - c

Quick question. For example, working with a some-what larger case of ~1000 options: which is the 'best' method? I'm not specifically wanting straight up faster results.
switch (foo) {
case 0:
// code ...
break;
// One, two, skip a few...
case 1000:
// code ...
}
or something that splits possible results so it can quickly find the proper case statement. Similar too:
if (foo < 101) {
if (foo < 51)
switch (foo) {}
else
switch (foo) {}
} else if (foo > 100 && foo < 201) {
// skipped for convenience
} else if (foo > 900) {
if (foo < 951)
switch (foo) {}
else
switch (foo) {}
}
I imagine the second method is much faster for the larger numbers, but the first method also seems it may be able to breeze through it since it's not constantly checking statements. Is one of these methods frowned upon or is there a better method? This is for C, but I am interested in knowing its consistency with other languages. Thanks!

switch statements can be incredibly fast if the compiler implements them using jump tables, but this is only possible on special sequence of cases, and may not be practical it really depends on the possible cases. The compiler may or may not use jump tables, I did find this http://blog.jauu.net/2010/06/15/GCC-generated-Switch-Jump-Tables/ which was kind of interesting.
JUMP tables can be incredibly fast, since it just calculates the offset and jumps to the appropriate address.
GCC does have -fno-jump-tables which does disable it completely.
Sometimes you can build your own jump table, using arrays of function pointers, and special indices, this can make your code incredibly fast but its not practical in all cases, imagine you had a switch and in every case you would call a function, you could build an array of function pointers, set a default function just to be safe, then instead of a switch you would simply do fun_table[indice](); I did this once for my own virtual machine.

I think switch statements are often interpreted as goto's in the underlying assembly language, which would make the first method significantly faster.
This seems to support that, although it isn't exactly proof: http://en.wikibooks.org/wiki/Optimizing_C%2B%2B/Writing_efficient_code/Performance_improving_features#Case_values_of_switch_statements

I believe that the switch statement is better, at least from a code readability standpoint (and maybe from a speed standpoint since it's only picking out one block to run as apposed to have to evaluate multiple conditions, as in the second example.)

Is it not recommended that any function should fit onto about 1.5 screens, so such a huge switch statement will not fit this bill. To overcome this have a dispatch table.All you have to do is index into the array to find the appropriate function to call.

I'm posting this just for information purpose, since samy.vilar already gave the most elegant solution with the function array. If you use GCC, it understands case range. This code would eventually behave in quite similar way as your second solution, resulting in some binary-tree code path (assuming there is no compiler optimization).
int nested_switch(int i)
{
switch (i) {
/* i is in the 1..10 range */
case 1 .. 10:
switch (i) {
/* i is in the 0..5 range */
case 1 .. 5:
switch (i) {
case 1:
break;
case 2:
break;
...
case 5:
break;
}
case 5 .. 10:
switch (i) {
case 6:
break;
case 7:
break;
...
case 10:
break;
}
}
/* i is in the 11..20 range */
case 11 .. 20:
switch (i) {
...
}
}
return 0;
}

Related

Is there any better implementation for this switch case construct?

I'm working on an embedded system where a register hast to be accessed and after that to be incremented to achieve the result I'm looking for, since the machine is notifying and configured to react on my access and changing or not changing the flag. So the switch's argument has to be kept as it is, since it would otherwise change the behaving of the embedded system.
But there may occur a situation where I don't want to get any of the cases get invoked. But I still need to acces and increment the argument of the switch.
(More indepth I'm converting a sequence of analog values to digital values conversions step by step. The index is used to stay synchronized with the current conversion and relating it with the corresponding case to handle the figure correct. There may occur a state in which the index desynchronisizes to the current conversion so the sequence of conversions must be run through without any of the cases getting invoked (to prevent setting wrong data) untill the sequence is finished and the resynchroinisation can get performed)
The way I'm currently doing this is this:
switch (RunIndex++)/*RunIndex may only be accessed one time per execution
of this construct and has to be incremented in the same step. thats given.*/
{
if (RunIndexSyncedWithADCensured == false)
{
break;
}
case 0:
Case0RelatedData = SomeOperationsForCase0(RawData);
break;
case 1:
Case1RelatedData = SomeOperationsForCase1(RawData);
break;
case 2:
Case2RelatedData = SomeOperationsForCase2(RawData);
break;
default:
RunIndex = 0;
break;
}
This construct does the job but it looks like it is a bit controversial and I don't feel well by considering about committing this into productinal code.
So is there a better looking way to achieve the same, without the need of additional variables or assignements?
note:
Also it may be relevant, that this is in the first part of a interupt function consisting of 2 parts.
The first part handles what has to happen if() a conversion is finished. The second part, what has additional to be done if() this conversion also ended the sequence. So it is no option to simply return from the function without getting into the second part. and there is currently no loop structure where an if(...)break; may break out. (What is also the reason why I'm putting the if inside the switch scope, as it is at least by standard a valid way to break out.)
Firstly, the if() inside switch() will never be executed.
Consider the below code snippet:
#include <stdio.h>
int main(int argc, char *argv[])
{
int i = 2;
switch(i) {
if (i == 2) {
printf("I M HERE\n");
}
case 1:
printf("1\n");
break;
case 2:
printf("2\n");
break;
default:
printf("default\n");
break;
}
return 0;
}
For your code: you expect the string I M HERE to be printed. But that is not the case.
The output for the above code snippet is:
2
No statements before case/default(switch constructs): is executed inside switch
Now to answer for
I don't want to get any of the cases get invoked. But I still need to acces and increment the argument of the switch
Just move the if() outside to the switch().
if (RunIndexSyncedWithADCensured) {
switch (RunIndex++) {
case 0:
Case0RelatedData = SomeOperationsForCase0(RawData);
break;
/* Other cases here */
default:
RunIndex = 0;
break;
}
} else
RunIndex++;
Why not save the value first and then increment it and use the saved value in the switch? By the way this also includes two accesses, first to read the value from RunIndex and the second to increment it.
int runIndex = (RunIndex++);
if (RunIndexSyncedWithADCensured )
{
switch (runIndex)/*RunIndex may only be accessed one time per execution
of this construct and has to be incremented in the same step. thats given.*/
{
case 0:
Case0RelatedData = SomeOperationsForCase0(RawData);
break;
case 1:
Case1RelatedData = SomeOperationsForCase1(RawData);
break;
case 2:
Case2RelatedData = SomeOperationsForCase2(RawData);
break;
default:
RunIndex = 0;
break;
}
}
Since you are using adjacent index numbers, you could make an array of function pointers to replace the switch. That's what the optimizer will turn the switch into anyhow. So instead of your obscure switch, you get this:
if (RunIndexSyncedWithADCensured)
{
SomeOperationsForCase[RunIndex](RawData);
}
RunIndex++;
if (RunIndex > MAX)
{
RunIndex = 0;
}
Completely unrelated to the switch statement design: in case RunIndex is a sensitive volatile variable such as some hardware register, then you shouldn't use it directly in any form of computations. Make a copy of it:
volatile int RunIndex;
...
int index = RunIndex; // read from RunIndex
if (RunIndexSyncedWithADCensured)
{
SomeOperationsForCase[index](RawData);
}
index++;
if (index > MAX)
{
index = 0;
}
RunIndex = index; // write to RunIndex
This is standard practice for all such volatile variables.

Working with mathematical operations received as input

Let's say I'd like to receive two mathematical operations from a user (e.g. + - %) and calculate numbers accordingly. Let's also say I can use one if/else statement to determine precedence (and that all operations have different precedences).
I have several ideas in mind for implementation, and would like feedback regarding which is considered "better" coding (clearer, more efficient, etc.).
I could do something like this:
if (firstOperator >= secondOperator){
switch (firstOperator){
case '+':
switch (secondOperator)
// insert all 6 possible cases
case '-':
switch (secondOperator)
// insert all 5 possible cases
...
...
}
else{
// same idea as above
}
Or I could simply hard-code all options by creating one switch for every option of firstOperation, and nest a second switch in each of those cases for all possible secondOperation.
The two approaches are different, and I have one or two more. I would have thought that the first is more "correct" and elegant, but it actually results in more lines of code than the "brute-force" all-out second option.
I would love to hear any input regarding this kind of coding.
Note: I'm talking about only very basic C programming (i.e. without using other data structures like stacks, etc. Just the basic if/else, switch, loops, etc.
Here's how I would have done it, but it depends on your first and second operations being independently handled (which I think should be possible if what you are doing is an expression evaluator). In my example, I assume there is a queue holding the arguments that were parsed in the order they were parsed.
if (firstOperator >= secondOperator) {
handle(firstOperator);
handle(secondOperator);
} else {
// Assuming something like 1 + 2 * 3, with 1 2 3 in the queue:
//
// tmp = dequeueArg() makes the queue: 2 3
// handle('*') makes the queue: 6
// pushFront(tmp) makes the queue: 1 6
// handle('+') makes the queue: 7
//
int tmp = dequeueArg();
handle(secondOperator);
pushFront(tmp);
handle(firstOperator);
}
void handle(Op operator)
{
int x = dequeueArg();
int y = dequeueArg();
switch (operator) {
case '+': pushFront(x+y); break;
case '-': pushFront(x-y); break;
case '*': pushFront(x*y); break;
case '/': pushFront(x/y); break; // Maybe check for 0
case '%': pushFront(x%y); break; // Maybe check for 0
case '&': pushFront(x&y); break;
etc...
}
}
What I wrote here probably will not work as a general infix parser with precedence. It's more an example of how to not use O(N^2) nested case statements.

optimizing switch case code

I have below switch case in my code.
switch(condition)
case 'A' :
//Code part A
break;
case 'B' :
//Code part A
//Code part B
break;
case 'C' : //Some code
break;
code Part A is repeated in both case 'A' and case 'B'. I want to avoid duplication of code.
If we use fall though then we need to add an if condition for case B. Is this the only way for avoiding repetition of code?
If the order is not important, you can simply do:
switch (condition)
{
case 'B':
// Code part B
// no break
case 'A':
// Code part A
break;
...
}
A case 'B' will continue to execute through the case 'A' code because you didn't call a break.
Manipulating a switch statement to reduce duplication of code may work at first, but then you may add additional cases to the switch later, which may break that cleanness of that optimization. For example:
switch(condition)
case 'A' :
// Code part A
break;
case 'B' :
// Code part A
// Code part B
break;
case 'C' :
// Code part C
break;
case 'D' :
// Code part A
// Code part D
break;
Suddenly an optimization which seemed nice at the time, starts to become difficult to maintain, difficult to read and error prone.
Having already determined that there is common code, the cleanest response in my view is to write functions to perform the common code and call from each case. Going forward, this will continue to be maintainable.
Unfortunately, that's the only way, short of defining a function for partA.
You can reduce nesting by exiting the switch from inside the combined case label to make the code look a little more uniform:
switch (someValue) {
case 'A':
case 'B':
// Code part A
if (someValue == 'A') break;
// Code part B
break;
case 'C':
break;
}
This lets your part A and part B code have the same level of nesting.
Can "//Code part B" be executed before "//Code part A"? If so, you could just reorder them and let it fall through without an if condition.
I don't think there's much else to do, otherwise. One of the reasons for the creation of object-oriented languages was avoiding the duplication of code you have in imperative languages.

What does switch do if there is no default case?

I have found a following piece of code:
switch(val){
case 0:
// some actions
break;
case 1:
// some actions
break;
case 2:
// some actions
break;
}
But it is not clear enough what will happen in the case of e.g val = 10?
I tried to test this code in a short program with incorrect value, and nothing had happen - program exited normally.
Can this code cause any potential error? Is there any guarantee that nothing will happen?
It will simply do nothing and not enter in any case.
It is recommended to have a default clause as the final clause in a switch statement. Programs like Lint will warn if you forget the default clause. And for information note that the default clause is required in MISRA-C.
EDIT:
I personally prefer it to be the final clause but I think the most important is for the final clause to be present. Why I prefer it to be the final clause is because of the Principle of least astonishment: people are used to see it as the final clause so I think it eases the program reading.
And just for information as I mentioned Lint and MISRA-C in my answer: PC-Lint / flexelint will not warn if default is present but not as the final clause and MISRA-C explicitly requires default to be present as the final clause.
That is why you should have a default case. It will handle cases other than those you typed.
What Happens in your case is that, it checks the case 0 and it doesn't match and checks case 1 and it also doesn't match and checks the case 2 and it again doesn't match. so it exits..
So it should be this way:
switch(val){
case 0:
// some actions
break;
case 1:
// some actions
break;
case 2:
// some actions
break;
default:
//some actions
break;
}
Another small point to note: it should case 0: not case 0;
If you use any other value from 0, 1, 2 (in this example) nothing will happen.
val will be compared with all values that are in cases and if it will not be equal to one of them, it just will jump to the next statement.

Switch statement with returns -- code correctness [closed]

Closed. This question is opinion-based. It is not currently accepting answers.
Want to improve this question? Update the question so it can be answered with facts and citations by editing this post.
Closed 1 year ago.
The community reviewed whether to reopen this question 1 year ago and left it closed:
Original close reason(s) were not resolved
Improve this question
Let's say I have code in C with approximately this structure:
switch (something)
{
case 0:
return "blah";
break;
case 1:
case 4:
return "foo";
break;
case 2:
case 3:
return "bar";
break;
default:
return "foobar";
break;
}
Now obviously, the breaks are not necessary for the code to run correctly, but it sort of looks like bad practice if I don't put them there to me.
What do you think? Is it fine to remove them? Or would you keep them for increased "correctness"?
Remove the break statements. They aren't needed and perhaps some compilers will issue "Unreachable code" warnings.
I would take a different tack entirely. Don't RETURN in the middle of the method/function. Instead, just put the return value in a local variable and send it at the end.
Personally, I find the following to be more readable:
String result = "";
switch (something) {
case 0:
result = "blah";
break;
case 1:
result = "foo";
break;
}
return result;
I would remove them. In my book, dead code like that should be considered errors because it makes you do a double-take and ask yourself "How would I ever execute that line?"
Remove them. It's idiomatic to return from case statements, and it's "unreachable code" noise otherwise.
Personally I would remove the returns and keep the breaks. I would use the switch statement to assign a value to a variable. Then return that variable after the switch statement.
Though this is an arguable point I've always felt that good design and encapsulation means one way in and one way out. It is much easier to guarantee the logic and you don't accidentally miss cleanup code based on the cyclomatic complexity of your function.
One exception: Returning early is okay if a bad parameter is detected at the beginning of a function--before any resources are acquired.
I'd normally write the code without them. IMO, dead code tends to indicate sloppiness and/or lack of understanding.
Of course, I'd also consider something like:
char const *rets[] = {"blah", "foo", "bar"};
return rets[something];
Edit: even with the edited post, this general idea can work fine:
char const *rets[] = { "blah", "foo", "bar", "bar", "foo"};
if ((unsigned)something < 5)
return rets[something]
return "foobar";
At some point, especially if the input values are sparse (e.g., 1, 100, 1000 and 10000), you want a sparse array instead. You can implement that as either a tree or a map reasonably well (though, of course, a switch still works in this case as well).
If you have "lookup" type of code, you could package the switch-case clause in a method by itself.
I have a few of these in a "hobby" system I'm developing for fun:
private int basePerCapitaIncomeRaw(int tl) {
switch (tl) {
case 0: return 7500;
case 1: return 7800;
case 2: return 8100;
case 3: return 8400;
case 4: return 9600;
case 5: return 13000;
case 6: return 19000;
case 7: return 25000;
case 8: return 31000;
case 9: return 43000;
case 10: return 67000;
case 11: return 97000;
default: return 130000;
}
}
(Yep. That's GURPS space...)
I agree with others that you should in most cases avoid more than one return in a method, and I do recognize that this one might have been better implemented as an array or something else. I just found switch-case-return to be a pretty easy match to a lookup table with a 1-1 correlation between input and output, like the above thing (role-playing games are full of them, I am sure they exist in other "businesses" as well) :D
On the other hand, if the case-clause is more complex, or something happens after the switch-statement, I wouldn't recommend using return in it, but rather set a variable in the switch, end it with a break, and return the value of the variable in the end.
(On the ... third? hand... you can always refactor a switch into its own method... I doubt it will have an effect on performance, and it wouldn't surprise me if modern compilers could even recognize it as something that could be inlined...)
Keep the breaks - you're less likely to run into trouble if/when you edit the code later if the breaks are already in place.
Having said that, it's considered by many (including me) to be bad practice to return from the middle of a function. Ideally a function should have one entry point and one exit point.
What do you think? Is it fine to remove them? Or would you keep them for increased "correctness"?
It is fine to remove them. Using return is exactly the scenario where break should not be used.
I would say remove them and define a default: branch.
Wouldn't it be better to have an array with
arr[0] = "blah"
arr[1] = "foo"
arr[2] = "bar"
and do return arr[something];?
If it's about the practice in general, you should keep the break statements in the switch. In the event that you don't need return statements in the future, it lessens the chance it will fall through to the next case.
For "correctness", single entry, single exit blocks are a good idea. At least they were when I did my computer science degree. So I would probably declare a variable, assign to it in the switch and return once at the end of the function
Interesting. The consensus from most of these answers seems to be that the redundant break statement is unnecessary clutter. On the other hand, I read the break statement in a switch as the 'closing' of a case. case blocks that don't end in a break tend to jump out at me as potential fall though bugs.
I know that that's not how it is when there's a return instead of a break, but that's how my eyes 'read' the case blocks in a switch, so I personally would prefer that each case be paired with a break. But many compilers do complain about the break after a return being superfluous/unreachable, and apparently I seem to be in the minority anyway.
So get rid of the break following a return.
NB: all of this is ignoring whether violating the single entry/exit rule is a good idea or not. As far as that goes, I have an opinion that unfortunately changes depending on the circumstances...
I say remove them. If your code is so unreadable that you need to stick breaks in there 'to be on the safe side', you should reconsider your coding style :)
Also I've always prefered not to mix breaks and returns in the switch statement, but rather stick with one of them.
I personally tend to lose the breaks. Possibly one source of this habit is from programming window procedures for Windows apps:
LRESULT WindowProc (HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
switch (uMsg)
{
case WM_SIZE:
return sizeHandler (...);
case WM_DESTROY:
return destroyHandler (...);
...
}
return DefWindowProc(hwnd, uMsg, wParam, lParam);
}
I personally find this approach a lot simpler, succinct and flexible than declaring a return variable set by each handler, then returning it at the end. Given this approach, the breaks are redundant and therefore should go - they serve no useful purpose (syntactically or IMO visually) and only bloat the code.
I think the *break*s are there for a purpose. It is to keep the 'ideology' of programming alive. If we are to just 'program' our code without logical coherence perhaps it would be readable to you now, but try tomorrow. Try explaining it to your boss. Try running it on Windows 3030.
Bleah, the idea is very simple:
Switch ( Algorithm )
{
case 1:
{
Call_911;
Jump;
}**break**;
case 2:
{
Call Samantha_28;
Forget;
}**break**;
case 3:
{
Call it_a_day;
}**break**;
Return thinkAboutIt?1:return 0;
void Samantha_28(int oBed)
{
LONG way_from_right;
SHORT Forget_is_my_job;
LONG JMP_is_for_assembly;
LONG assembly_I_work_for_cops;
BOOL allOfTheAbove;
int Elligence_says_anyways_thinkAboutIt_**break**_if_we_code_like_this_we_d_be_monkeys;
}
// Sometimes Programming is supposed to convey the meaning and the essence of the task at hand. It is // there to serve a purpose and to keep it alive. While you are not looking, your program is doing // its thing. Do you trust it?
// This is how you can...
// ----------
// **Break**; Please, take a **Break**;
/* Just a minor question though. How much coffee have you had while reading the above? I.T. Breaks the system sometimes */
Exit code at one point. That provides better readability to code. Adding return statements (Multiple exits) in between will make debugging difficult .
Simply define variable and return it at last of the switch statement and we can also remove default statement by setting variable= default value.
Ex:
switch(someVariable)
{
case 'a':
return a;
break;
case 'b':
return b;
break;
default:
return c;
}
solution:
$result = c; //for default value
switch(someVariable)
{
case 'a':
$result = a;
break;
case 'b':
$result = b;
break;
}
return $result; //simply return $result
This will lead to reduce your return statement.

Resources