How Switch case Statement Implemented or works internally? - c++

I read somewhere that the switch statement uses "Binary Search" or some sorting techniques to exactly choose the correct case and this increases its performance compared to else-if ladder.
And also if we give the case in order does the switch work faster? is it so? Can you add your valuable suggestions on this?
We discussed here about the same and planned to post as a question.

It's actually up to the compiler how a switch statement is realized in code.
However, my understanding is that when it's suitable (that is, relatively dense cases), a jump table is used.
That would mean that something like:
switch(i) {
case 0: doZero(); break;
case 1: doOne();
case 2: doTwo(); break;
default: doDefault();
}
Would end up getting compiled to something like (horrible pseudo-assembler, but it should be clear, I hope).
load i into REG
compare REG to 2
if greater, jmp to DEFAULT
compare REG to 0
if less jmp to DEFAULT
jmp to table[REG]
data table
ZERO
ONE
TWO
end data
ZERO: call doZero
jmp END
ONE: call doOne
TWO: call doTwo
jmp END
DEFAULT: call doDefault
END:
If that's not the case, there are other possible implementations that allow for some extent of "better than a a sequence of conditionals".

How swtich is implemented depends on what values you have. For values that are close in range, the compiler will generally generate a jump table. If the values are far apart, it will generate a linked branch, using something like a binary search to find the right value.
The order of the switch statements as such doesn't matter, it will do the same thing whether you have the order in ascending, descending or random order - do what makes most sense with regard to what you want to do.
If nothing else, switch is usually a lot easier to read than an if-else sequence.

On some googling I found some interestin link and planned to post as an answer to my question.
http://www.codeproject.com/Articles/100473/Something-You-May-Not-Know-About-the-Switch-Statem
Comments are welcome..

Although it can be implemented as several ways it depends on how the language designer wants to implement it.
One possible efficient way is to use Hash Maps
Map every condition (usually integer) to the corresponding expression to be evaluated followed by a jump statement.
Other solutions also might work as often switch has finite conditions but a efficient solution shall be to use Hash map

Related

Remove/minimize Git merge conflicts

I am trying to think of a way to completely remove or minimize Git merge conflicts for the following scenario:
switch(value)
{
case OLD_CASE_1:
case OLD_CASE_2:
case NEW_CASE_1:
case NEW_CASE_2:
case NEW_CASE_3:
case NEW_CASE_4:
return true;
default:
return false;
}
For each of the new cases, I create a branch where I add just the case specific to that branch. (Eg. feature/new-case-x contains just case NEW_CASE_X:).
At the end of the day, I submit 4 pull requests. As soon as any one of them is merged, the others will enter a conflict state. Since the case order doesn't matter to me, is there a way I can minimize or completely get rid of conflicts? Thank you.
One way would be to do an immediate check-in/promotion with a marker label after creating the named test branch.
The creation of the marker label may be as trivial as a comment, or a pair of comments, so would avoid needing a test cycle before promotion. Perhaps use the branch name to "decorate" the comment. By immediately, I do mean it! So long as 2 new test branches are not both created simultaneously in this small window, they now each have a space to actually write their code that should be conflict free.
You could do the same with the test body, if you have issues with people simultaneously appending tests in existing files: Create a comment block denoting the start and end of their test. So long as they write between the lines a conflict is avoided. This does mean they have to choose which test module they want to append to straight away, of course.
The short answer is no. As R Sahu noted in a comment, Git has no idea about the semantics of the text it is merging. It merely treats it as a set of lines. If, while merging two different change-sets, the lines overlap or abut, you get a merge conflict. For instance, given:
case OLD_CASE_1:
case OLD_CASE_2:
+ case NEW_CASE_1:
return true;
vs
case OLD_CASE_1:
case OLD_CASE_2:
+ case NEW_CASE_2:
return true;
Git would in general declare a conflict here. Were this Go code, rather than C++, Git would be "more right" about this being a true conflict, since Go has no automatic fall-through (or equivalently, has the C++ equivalent of a default break; in front of each case), i.e., in C++ the semantics would be to return true only for the one new case, and no longer for OLD_CASE_2.
Now, if you're in a group that prefers to rebase pull requests, your automatic rebasing will tend to go smoothly if the NEW_CASE_1 PR is accepted and merged first and you build your second PR on the first one and you rebase each of your remaining PRs on the accepted PRs in order. This is more complicated, and prone to a lot more re-work if your PRs must be accepted in some other order for some reason, but sometimes it's pretty nice. Whether you and/or your group want to do this is a much bigger question, though.

standard alternative for non-standard gnu case ranges

I have a question for a quick workaround to enjoy the benefits of the non-standard gnu case ranges. For example, the non-standard:
case 1 ... 5:
Could be replaced by:
case 1:
case 2:
case 3:
case 4:
case 5:
Probably some macro solution might be in order. From my memory macro loops cannot loop for large numbers of iterations. For this reason, what if the range is "large", say in the thousands?
If you're talking preprocessor loops I guess that you're thinking of the preprocessor meta programming from boost. While it's probably quite portable, the loops seems to be limited to 255 "iterations". In fact the implementation is not a real loop, it's more like a hard coded loop-unroll (thereby the limitation). You could of course expand this to more iterations.
While the preprocessor trick could be tempting, I think you should consider using if-else if-else construct. What's actually (often) happens in a modern compiler regarding conditionals is that it boils down to the same construct that should generate the same code (unless you trick the compiler into evaluating the variable multiple times).
You could even combine the constructs, using a switch-case construct for all singular alternatives and then after the default label add an if-else if-else to handle all ranges.
A third solution would be to write a script that finds the case-ranges and replace them by a standard construct, this should be fairly straight forward in most cases as case can't appear in many places without being a keyword and then it should be followed by an expression which can't contain ... in that way. The only problematic situation (that I can think of) would be when the case-range is a result of preprocessor expansion.
The best alternative would be to re-factor the code to use if/else. If there truly are thousands of cases it may or may not be very efficient to have a giant case statement in the first place.
However, it because cases could "fall-through" or other odd flow control like Duff's device (I hope not), it may not be completely a straightforward conversion.
It is not likely to be a very good implementation to abuse the preprocessor to "loop". See Writing a while loop in the C preprocessor for sample of what this might look like.
It may be best to write a simple python or awk script. However this approach may also be flawed if the keyword case appears somewhere like a string or if labels the preprocessor changes anything. This may work very well for a narrow one-off conversion though, but without seeing the code in question it is hard to say.
There is a serious problem with either preprocessing approach if the case labels use enumerations. Since enums are still just text strings at the time the preprocessor runs (or an external script), how can it iterate from STATE_10 to STATE_20 without knowing what integers they represent? It can't - the GNU extension really requires compiler support.
If a one-time wholesale replacement of the case statement is too invasive or irregular to manage, you could probably utilize a hybrid approach:
Assuming you have a (notional) example like:
switch(state)
{
case STATE_1:
xxx; break;
case STATE_2 ... STATE_10:
yyy; break;
}
Allocate a previously unused range of indexes. Add one new special index for each existing range label. Use if/else logic to detect the ranges first and then replace the range case with a new standard one. This allows the control flow structure to remain essentially unmodified:
#if !defined(__GNUC__)
#define STATE_RANGE_2_10 101
if(state >= 2 && state <= 10)
state2 = STATE_RANGE_2_10
else if(...)
state2 = STATE_RANGE_x_y
else
state2 = state;
#else /* GNU */
#define STATE_RANGE_2_10 STATE_2 ... STATE_10
state2 = state;
#endif
switch(state2)
{
case STATE_1:
xxx; break;
case STATE_RANGE_2_10:
yyy; break;
}
With some suitable macros this could even be made portable between GNUC and real C if you really wanted GNUC to still use the extension for some reason. Note: I introduced the state2 variable in case it is stored or used outside the local scope. If not, you can skip that.

Would this method of looping be a bad idea?

I'm building a html/xml slicer (something that cuts the text into a list of meaningful blocks like elementStart, plainText etc.. which I can then use to construct the elements in an OO manner).
I found it convenient to create a logic sub for processing each of the various modes, the main loop info is held in class variables while the sub's do some work and then pass the torch to another one depending on what data they encounter. It occurred to me though, that this might cause some problems (like overflowing the stack? idk) since technically, it doesn't exit a single one of the subs until the entire process is complete. Heres what I mean: (in pseudo code)
void plainLogic() {
// look for '<' with something other than space after it
// add the gathered data to the slice list
switch (data[it]) // <- the something other
{
case '!':
commentLogic();
break;
case '/':
elEndLogic();
break;
default:
elStartLogic();
break;
}
}
and the other *Logic subs are pretty much the same: find the extent of data, bag the goods, go somewhere else. I realized just a little while ago though, that it doesn't actually go anywhere, it just goes deeper and actually has to come back.
Is this bad? Would it be Ok if none of the subs had any sub scope variables? preferred alternatives? Maybe there is like a special return keyword that executes another function after exiting the sub?

Does replacing statements by expressions using the C++ comma operator could allow more compiler optimizations?

The C++ comma operator is used to chain individual expressions, yielding the value of the last executed expression as the result.
For example the skeleton code (6 statements, 6 expressions):
step1;
step2;
if (condition)
step3;
return step4;
else
return step5;
May be rewritten to: (1 statement, 6 expressions)
return step1,
step2,
condition?
step3, step4 :
step5;
I noticed that it is not possible to perform step-by-step debugging of such code, as the expression chain seems to be executed as a whole. Does it means that the compiler is able to perform special optimizations which are not possible with the traditional statement approach (specially if the steps are const or inline)?
Note: I'm not talking about the coding style merit of that way of expressing sequence of expressions! Just about the possible optimisations allowed by replacing statements by expressions.
Most compilers will break your code down into "basic blocks", which are stretches of code with no jumps/branches in or out. Optimisations will be performed on a graph of these blocks: that graph captures all the control flow in the function. The basic blocks are equivalent in your two versions of the code, so I doubt that you'd get different optimisations. That the basic blocks are the same isn't entirely obvious: it relies on the fact that the control flow between the steps is the same in both cases, and so are the sequence points. The most plausible difference is that you might find in the second case there is only one block including a "return", and in the first case there are two. The blocks are still equivalent, since the optimiser can replace two blocks that "do the same thing" with one block that is jumped to from two different places. That's a very common optimisation.
It's possible, of course, that a particular compiler doesn't ignore or eliminate the differences between your two functions when optimising. But there's really no way of saying whether any differences would make the result faster or slower, without examining what that compiler is doing. In short there's no difference between the possible optimisations, but it doesn't necessarily follow that there's no difference between the actual optimisations.
The reason you can't single-step your second version of the code is just down to how the debugger works, not the compiler. Single-step usually means, "run to the next statement", so if you break your code into multiple statements, you can more easily debug each one. Otherwise, if your debugger has an assembly view, then in the second case you could switch to that and single-step the assembly, allowing you to see how it progresses. Or if any of your steps involve function calls, then you may be able to "do the hokey-cokey", by repeatedly doing "step in, step out" of the functions, and separate them that way.
Using the comma operator neither promotes nor hinders optimization in any circumstances I'm aware of, because the C++ standard guarantee is only that evaluation will be in left-to-right order, not that statement execution necessarily will be. (This is the same guarantee you get with statement line order.)
What it is likely to do, though, is turn your code into a confusing mess, since many programmers are unaware that the comma-as-operator even exists, and are apt to confuse it with commas used as parameter separators. (Want to really make your code unreadable? Call a function like my_func((++i, y), x).)
The "best" use of the comma operator I've seen is to work with multiple variables in the iteration statement of a for loop:
for (int i = 0, j = 0;
i < 10 && j < 12;
i += j, ++j) // each time through the loop we're tinkering with BOTH i and j
{
}
Very unlikely IMHO. The thing get's compiled down to assembler/machine code, then further low-level optimizations are done, so it probably turns out to the same thing.
OTOH, if the comma operator is overloaded, the game changes completely. But I'm sure you know that. ;)
The obligatory list:
Don't worry about rewriting almost equivalent code to gain performance
If you have a perf-problem, profile to see what the problem is
If you can't get it faster by algorithmic ops, look at the disassembly and see that the compiler does what you intended
If not, ask here and post source and disassembly for both versions. :)

Why Switch/Case and not If/Else If?

This question in mainly pointed at C/C++, but I guess other languages are relevant as well.
I can't understand why is switch/case still being used instead of if/else if. It seems to me much like using goto's, and results in the same sort of messy code, while the same results could be acheived with if/else if's in a much more organized manner.
Still, I see these blocks around quite often. A common place to find them is near a message-loop (WndProc...), whereas these are among the places when they raise the heaviest havoc: variables are shared along the entire block, even when not propriate (and can't be initialized inside it). Extra attention has to be put on not dropping break's, and so on...
Personally, I avoid using them, and I wonder wether I'm missing something?
Are they more efficient than if/else's?
Are they carried on by tradition?
Summarising my initial post and comments - there are several advantages of switch statement over if/else statement:
Cleaner code. Code with multiple chained if/else if ... looks messy and is difficult to maintain - switch gives cleaner structure.
Performance. For dense case values compiler generates jump table, for sparse - binary search or series of if/else, so in worst case switch is as fast as if/else, but typically faster. Although some compilers can similarly optimise if/else.
Test order doesn't matter. To speed up series of if/else tests one needs to put more likely cases first. With switch/case programmer doesn't need to think about this.
Default can be anywhere. With if/else default case must be at the very end - after last else. In switch - default can be anywhere, wherever programmer finds it more appropriate.
Common code. If you need to execute common code for several cases, you may omit break and the execution will "fall through" - something you cannot achieve with if/else. (There is a good practice to place a special comment /* FALLTHROUGH */ for such cases - lint recognises it and doesn't complain, without this comment it does complain as it is common error to forgot break).
Thanks to all commenters.
Well, one reason is clarity....
if you have a switch/case, then the expression can't change....
i.e.
switch (foo[bar][baz]) {
case 'a':
...
break;
case 'b':
...
break;
}
whereas with if/else, if you write by mistake (or intent):
if (foo[bar][baz] == 'a') {
....
}
else if (foo[bar][baz+1] == 'b') {
....
}
people reading your code will wonder "were the foo expressions supposed to be the same", or "why are they different"?
please remember that case/select provides additional flexibility:
condition is evaluated once
is flexible enough to build things like the Duff's device
fallthrough (aka case without break)
as well as it executes much faster (via jump/lookup table) * historically
Also remember that switch statements allows the flow of control to continue, which allows you to nicely combine conditions while allowing you to add additional code for certain conditions, such as in the following piece of code:
switch (dayOfWeek)
{
case MONDAY:
garfieldUnhappy = true;
case TUESDAY:
case WEDNESDAY:
case THURSDAY:
case FRIDAY:
weekDay = true;
break;
case SATURDAY:
weekendJustStarted = true;
case SUNDAY:
weekendDay = true;
break;
}
Using if/else statements here instead would not be anywhere as nice.
if (dayOfWeek == MONDAY)
{
garfieldUnhappy = true;
}
if (dayOfWeek == SATURDAY)
{
weekendJustStarted = true;
}
if (dayOfWeek == MONDAY || dayOfWeek == TUESDAY || dayOfWeek == WEDNESDAY
|| dayOfWeek == THURSDAY || dayOfWeek == FRIDAY)
{
weekDay = true;
}
else if (dayOfWeek == SATURDAY || dayOfWeek == SUNDAY)
{
weekendDay = true;
}
If there are lots of cases, the switch statement seems cleaner.
It's also nice when you have multiple values for which you want the same behavior - just using multiple "case" statements that fall through to a single implementation is much easier to read than a if( this || that || someotherthing || ... )
It might also depend on your language -- For example, some languages switch only works with numeric types, so it saves you some typing when you're working with an enumerated value, numeric constants... etc...
If (day == DAYOFWEEK_MONDAY) {
//...
}
else if (day == DAYOFWEEK_TUESDAY) {
//...
}
//etc...
Or slightly easier to read...
switch (day) {
case DAYOFWEEK_MONDAY :
//...
case DAYOFWEEK_TUESDAY :
//...
//etc...
}
Switch/case is usually optimized more efficiently than if/else if/else, but is occasionally (depending on language and compiler) translated to simple if/else if/else statements.
I personally think switch statements makes code more readable than a bunch of if statements; provided that you follow a few simple rules. Rules you should probably follow even for your if/else if/else situations, but that's again my opinion.
Those rules:
Never, ever, have more than one line on your switch block. Call a method or function and do your work there.
Always check for break/ case fallthrough.
Bubble up exceptions.
Clarity. As I said here, a clue that else if is problematic is
the frequency with which ELSE IF is
used in a far more constrained way
than is allowed by the syntax. It is a
sledgehammer of flexibility,
permitting entirely unrelated
conditions to be tested. But it is
routinely used to swat the flies of
CASE, comparing the same expression
with alternate values...
This reduces the readability of the
code. Since the structure permits a
universe of conditional complexity,
the reader needs to keep more
possibilities in mind when parsing
ELSE IF than when parsing CASE.
Actually a switch statement implies that you are working off of something that is more or less an enum which gives you an instant clue what's going on.
That said, a switch on an enum in any OO language could probably be coded better--and a series of if/else's on the same "enum" style value would be at least as bad and even worse at conveying meaning.
addressing the concern that everything inside the switch has equivalent scope, you can always throw your case logic into another { } block, like so ..
switch( thing ) {
case ONETHING: {
int x; // local to the case!
...
}
break;
case ANOTHERTHING: {
int x; // a different x than the other one
}
break;
}
.. now I'm not saying that's pretty. Just putting it out there as something that's possible if you absolutely have to isolate something in one case from another.
one other thought on the scope issue - it seems like a good practice to only put one switch inside a function, and not a lot else. Under those circumstances, variable scope isn't as much of a concern, since that way you're generally only dealing with one case of execution on any given invocation of the function.
ok, one last thought on switches: if a function contains more than a couple of switches, it's probably time to refactor your code. If a function contains nested switches, it's probably a clue to rethink your design a bit =)
switch case is mainly used to have the choice to made in the programming .This is not related the conditional statement as :
if your program only require the choice to make then why you use the if/else block and increase the programming effort plus it reduce the execution speed of the program .
Switch statements can be optimized for speed, but can take up more memory if the case values are spread out over large numbers of values.
if/else are generally slow, as each value needs to be checked.
A Smalltalker might reject both switch and if-then-else's and might write something like:-
shortToLongDaysMap := Dictionary new.
shortToLongDaysMap
at: 'Mon' put: 'Monday';
at: 'Tue' put: 'Tuesday';
at: 'Wed' put: 'Wednesday'
etc etc.
longForm := shortToLongDaysMap at: shortForm ifAbsent: [shortForm]
This is a trivial example but I hope you can see how this technique scales for large numbers of cases.
Note the second argument to at:IfAbsent: is similar to the default clause of a case statement.
The main reason behind this is Maintainability and readability. Its easy to make code more readable and maintainable with Switch/case statement then if/else. Because you have many if/else then code become so much messy like nest and its very hard to maintain it.
And some how execution time is another reason.
Pretty sure they compile to the same things as if/else if, but I find the switch/case easier to read when there are more than 2 or 3 elses.