Assume we have a following code:
switch (currentChar) {
case 'G':
case 'T':
case 'M':
case ';':
case '\r':
case '\n':
doSomething();
break;
}
If the first condition is met (currentChar == 'G') are the following cases also compared, or the program jumps straight to doSomething()?
What would be faster to execute: the switch-case, or an if with || operator?
Clarification:
I want doSomething to be executed if any of the conditions is met. I also know that the 'G' case will occur in some 99% of all cases. Can I assume that it will be compared as the first if I put it on top of the list?
If the first condition is met (currentChar == 'G') are the following cases also evaluated, or the program jumps straight to doSomething()?
It will immediately jump to execute doSomething()
What would be faster to execute: the switch-case, or an if with || operator?
I don't think it would make any difference with any decent modern c++ compiler, and the emitted code should be fairly the same.
What would be faster to execute: the switch-case, or an if with || operator?
Go for switch(). If you have an enum or integer with small value set, switch() will usually create a jump table.
Once currentCharis compared to 'G', instructions jump to instruction doSomething(). You cannot rely on order of your cases to "optimize" the switch.
Note that comparison is not necessary sequential.
switch may be implemented as jump table for example:
void foo_switch(char c)
{
switch (c) {
case '0': bar0(); break;
case '1': bar1(); break;
case '2': bar2(); break;
case '3': bar3(); break;
};
}
void foo_if(char c)
{
if (c == '0') {
bar0();
} else if (c == '1') {
bar1();
} else if (c == '2') {
bar2();
} else if (c == '3') {
bar3();
}
}
void foo_table(char c)
{
if ('0' <= c && c <= '3') {
using voidFPtr = void(*)();
voidFPtr funcs[] = {&bar0, &bar1, &bar2, &bar3};
funcs[c - '0']();
}
}
Questions about the performance outcome of a particular style of code are almost always a waste of time.
Here's how gcc5.3 deals with this code after an optimisation pass:
test(char):
cmpb $59, %dil
je .L3
jle .L6
cmpb $77, %dil
je .L3
cmpb $84, %dil
je .L3
cmpb $71, %dil
je .L3
.L1:
rep ret
.L6:
cmpb $10, %dil
je .L3
cmpb $13, %dil
jne .L1
.L3:
jmp doSomething()
I really don't think you could write anything faster without creating a 256-entry jump table, which would have its own consequences in terms of cache locality and exhaustion.
If the first condition is met (currentChar == 'G') are the following
cases also evaluated, or the program jumps straight to doSomething()?
It falls through until it finds a break or hits the end.
What would be faster to execute: the switch-case, or an if with || operator?
You should worry about code readability and supportability, so use whatever is more readable for you. Then if you have issue with program speed work on optimization.
For readability - of course that's subjective, but with switch you get less verbose code, as you do not have to repeat variable name multiple times:
if( currentChar == 'G' || currentChar == 'B' || currentChar == 'C' )
so I would prefer switch in this situation.
switch (currentChar) {
case 'G':
case 'T':
case 'M':
case ';':
case '\r':
case '\n':
doSomething();
break;
}
This makes doSomething() be called if currentChar is G, T, M, ;, \r or \n. It's faster to use a switch than just plain if, because switch statements are often optimized into jump tables. This is why a switch must operate on a constant integral value.
There is no guarantee for the order of checking in a switch case. There is also no guarantee for the order of execution of || if there are no side effects for the expressions.
Basically, if the only difference is timing, c++ guarantees nothing about the order of stuff, on the basis of the as-if rule.
If the first condition is met (currentChar == 'G') are the following cases also evaluated, or the program jumps straight to doSomething()?
In your example, it will straight away jump to doSomething(). In case you don't want to have this behavior, then you need to insert break statements as shown for one case below:
switch (currentChar) {
case 'G': /*things to be done */ break /* This break will take it out of switch*/;
case 'T':
case 'M':
case ';':
case '\r':
case '\n':
doSomething();
break;
}
Also, note that in your example, break is not needed, as it is the last statement of your switch statement. Please refer this link for a working example of switch statement.
What would be faster to execute: the switch-case, or an if with || operator?
Assuming that you are using a decent compiler, the difference is minimum so that it can be ignored. Please refer this So link, in case you need to know more specifics.
Edit for your clarification:
I want doSomething() to be executed if any of the conditions is met.
Yes, as per your code, doSomething() would be executed even if only one of the conditions is met.
I also know that the 'G' case will occur in some 99% of all cases. Can I assume that it will be compared as the first if I put it on top of the list?
The remaining cases won't be checked.
Related
so this is the code that im trying to get to work but it displays "duplicate case value" whenever it reaches for B
im a first year college student so i might have used a wrong format or i might be overlooking something i really dont seem to figure out the problem so i turn to you guys for help
char dep;
int exp;
cout<<"please enter your department, A, B OR C: ";
cin>>dep;
cout<<"please enter your years of experience ";
cin>>exp;
switch(dep)
{
case 'A' || 'a' :{
switch (exp) {
case 5:
cout<<"you will recieve a 5% raise and 2.5% extra due to your experience";
break;
defualt : cout<<"you get 5% raise";
break;
}
}
break;
case 'B' || 'b' :{
switch (exp) {
case 5:
cout<<"you will recieve a 2% raise and 2.5% extra due to your experience";
break;
defualt : cout<<"you get 2% raise";
break;
}
}
break;
Though it compiles (or would without the B version), and spells what you wanted if roughly translated to English, case 'A' || 'a' does not do what you think it does.
The expression after case is treated as an exact match for the selection statement — it's compared exactly to dep. You can't throw in a more complex expression and expect it to be "unrolled" into multiple comparisons. Think of switch/case as a simple lookup table, rather than an intelligent branching feature (that's what if is for!).
Perhaps confusingly, the expression 'A' || 'a' is valid in its own right, but (like any expression) it evaluates to a single value: either true or false, depending on whether either of the operands if "truthy". In this particular example, neither has ASCII value zero so both is truthy, and the expression is always true. It'll be converted to the type of dep (the rules say it becomes 1) and used for that exact lookup.
Since you did this with 'B' and 'b' too, you do then indeed have two equivalent cases.
Instead, write a separate case for each condition. Fortunately, since cases fall through, you don't need to repeat the "body" of the case: you can just put the two cases next to each other; just don't put a break between them:
case 'A':
case 'a':
// code here
break;
case 'B':
case 'b':
// code here
By the way, you misspelt default.
The following implementation of square produces a series of cmp/je statements like I would expect of a chained if statement:
int square(int num) {
if (num == 0){
return 0;
} else if (num == 1){
return 1;
} else if (num == 2){
return 4;
} else if (num == 3){
return 9;
} else if (num == 4){
return 16;
} else if (num == 5){
return 25;
} else if (num == 6){
return 36;
} else if (num == 7){
return 49;
} else {
return num * num;
}
}
And the following produces a data table for return:
int square_2(int num) {
switch (num){
case 0: return 0;
case 1: return 1;
case 2: return 4;
case 3: return 9;
case 4: return 16;
case 5: return 25;
case 6: return 36;
case 7: return 49;
default: return num * num;
}
}
Why is gcc unable to optimize the top one into the bottom one?
Dissassembly for reference: https://godbolt.org/z/UP_igi
EDIT: interestingly, MSVC generates a jump table instead of a data table for the switch case. And surprisingly, clang optimizes them to the same result.
The generated code for switch-case conventionally uses a jump table. In this case, the direct return through a look-up table seems to be an optimization making use of the fact that every case here involves a return. Though the standard makes no guarantees to that effect, I would be surprised if a compiler were to generate a series of compares instead of a jump-table for a conventional switch-case.
Now coming to if-else, it is the exact opposite. While switch-case executes in constant time, irrespective of the number of branches, if-else is optimized for a smaller number of branches. Here, you would expect the compiler to basically generate a series of comparisons in the order that you have written them.
So if I had used if-else because I expect most calls to square() to be for 0 or 1 and rarely for other values, then 'optimizing' this to a table-lookup could actually cause my code to run slower than I expect, defeating my purpose for using an if instead of a switch. So although it is debatable, I feel GCC is doing the right thing and clang is being overly aggressive in its optimization.
Someone had, in the comments, shared a link where clang does this optimization and generates lookup-table based code for if-else as well. Something notable happens when we reduce the number of cases to just two (and a default) with clang. It once again generates identical code for both if and switch, but this time,
switches over to compares and moves instead of the lookup-table approach, for both. This means that even the switch-favoring clang knows that the 'if' pattern is more optimal when the number of cases is small!
In summary, a sequence of compares for if-else and a jump-table for switch-case is the standard pattern that compilers tend to follow and developers tend to expect when they write code. However, for certain special cases, some compilers might choose to break this pattern where they feel it provides better optimization. Other compilers might just choose to stick to the pattern anyway, even if apparently sub-optimal, trusting the developer to know what he wants. Both are valid approaches with their own advantages and disadvantages.
One possible rationale is that if low values of num are more likely, for example always 0, the generated code for the first one might be faster. The generated code for switch takes equal time for all values.
Comparing the best cases, according to this table. See this answer for the explanation of the table.
If num == 0, for "if" you have xor, test, je (with jump), ret. Latency: 1 + 1 + jump. However, xor and test are independent so the actual execution speed would be faster than 1 + 1 cycles.
If num < 7, for "switch" you have mov, cmp, ja (without jump), mov, ret. Latency: 2 + 1 + no jump + 2.
A jump instruction that does not result to jump is faster than one that results to jump. However, the table does not define the latency for a jump, so it is not clear to me which one is better. It is possible that the last one is always better and GCC is simply not able to optimize it.
This question already has answers here:
Concise way to say equal to set of values in C++
(5 answers)
Closed 6 years ago.
I am working on a school assignment. What I want to do is not the focus of the assignment, merely something I would like to do better.
I have the following if statement where equation is a string
if( (equation[0]== "*") || (equation[0]== "/") || (equation[0]== "+") || (equation[0]== "-"))
All it does is check to see if the first and last characters of the string are one of 4 operators. This is long, bulky, and hopefully not the best way of doing this. Sadly I do not have access to regular expressions as this type of check would be very easy using them.
Is there a better way of writing the if statement without using regular expressions? Something along the lines of
if( equation[0] == ("/" || "*" || "+" || "-"))
How about
if(std::string("*/+-").find(equation[0])!=std::string::npos)
You may consider using switch operator
switch(equation[0]) {
case '/':
case '*':
case '+':
case '-':
//your code
break;
default:
//else statement
}
I don't think it is possible to do what you're asking.
Best you can do is put equation[0] in another shorter name variable.
std::string a = equation[0];
if( (a"*") || (a== "/") || (a== "+") || (a== "-"))
No, that's not possible. But I think it's always cleaner and more readable to
switch (equation[0]) {
case '*':
case '/':
case '+':
case '-':
//dostuff
break;
default:
//dostuff
}
This way, it's also really easy to replace (add or remove) new characters. If you would to it with a regular expression, that would be definetely more work to do.
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 7 years ago.
Improve this question
I want to loop over a sequence, but I want to dynamically choose where to start the loop within the sequence. I designed this flow pattern.
switch(offset){
start:
currentObject = objects[index++]; //a different object is chosen to be manipulated by the sequence of code
case 0:
sub_sequence(currentObject); // a sequence that is repeated within the larger sequence of the entire switch
if(enough_actions) break;
case 1:
sub_sequence(currentObject);
if(enough_actions) break;
case 2:
sub_sequence(currentObject);
if(enough_actions) break;
goto start;
}
It seems to fit my needs well but I've never seen this design before. Is there anything wrong with this design? Should I be inclined to use an alternative?
What you have constructed there is a Duff's device. While it avoids duplicate source code, it is not only difficult to understand for humans, but just as difficult to optimize for the compiler as well.
switch(offset)
{
case 0:
sub_sequence(currentObject); // a sequence that is repeated within the larger sequence of the entire switch
if(enough_actions) break;
case 1:
sub_sequence(currentObject);
if(enough_actions) break;
case 2:
sub_sequence(currentObject);
if(enough_actions) break;
//a different object is chosen to be manipulated by the sequence of code
currentObject = objects[index++];
while(true) {
sub_sequence(currentObject);
if(enough_actions) break;
sub_sequence(currentObject);
if(enough_actions) break;
sub_sequence(currentObject);
if(enough_actions) break;
currentObject = objects[index++];
}
}
By separating the loop from the variable entry point, you are giving the compiler much more freedom to perform optimizations.
In the original code, it was separated by the start: label and 3 case: labels which force the compiler to treat each code section in between two labels individually.
Without these labels, the compiler may now apply optimizations specific to switch statements to the switch block, as well possibly additional loop unrolling or other strategies to the while loop.
In the end, going for the more readable variant may yield machine code which is both more compact and faster.
This is arguably one of the few cases where "duplicating" code is acceptable, since the switch and the while block only look similar, but are still behaving entirely different.
EDIT1: Moved loop to the end of the switch statement in order to handle enough_actions correctly. The loop could have been placed outside the switch block if there had been no condition for an early exit.
BONUS: Switch free implementation:
for(;!enough_actions;offset = 0,currentObject = objects[index++]) {
for(int i = offset; i < 3 && !enough_actions; i++) {
sub_sequence(currentObject);
}
}
You could also do:
switch(offset)
{
do
{
currentObject = objects[index++]; //a different object is chosen to be manipulated by the sequence of code
case 0:
sub_sequence(); // a sequence that is repeated within the larger sequence of the entire switch
if(enough_actions) break;
case 1:
sub_sequence();
if(enough_actions) break;
case 2:
sub_sequence();
if(enough_actions) break;
}
while (1);
}
So you avoid the goto ;)
(Where as stated in comment, technically here is no sense to avoid goto if this behaving IS needed)
But yeh, you are right, both should fit your needs.
I've examined the assembly code produced by Microsoft compilers for the following fibonacci function, and the compiler was still able to slightly modify the unfolded loop sequence (I assume to optimize register dependencies).
unsigned int fib(unsigned int n)
{
unsigned int f0, f1;
f0 = n & 1; /* if n even, f0=0=fib(0), f1=1=fib(-1) */
f1 = 1 - f0; /* else f1=0=fib(0), f0=1=fib(-1) */
switch(n%8){
do{
f1 += f0;
case 7:
f0 += f1;
case 6:
f1 += f0;
case 5:
f0 += f1;
case 4:
f1 += f0;
case 3:
f0 += f1;
case 2:
f1 += f0;
case 1:
f0 += f1;
case 0:
continue;
}while(0 <= (int)(n -= 8));
}
return f0;
}
Produced assembly code:
_fib PROC ; _n$ = eax
push esi
mov esi, eax
and eax, 1
mov edx, esi
mov ecx, 1
and edx, 7
sub ecx, eax
cmp edx, 7
ja SHORT $LN9#fib
jmp DWORD PTR $LN17#fib[edx*4]
$LN10#fib:
sub esi, 8
js SHORT $LN9#fib
add ecx, eax
$LN8#fib:
add eax, ecx
$LN7#fib:
add ecx, eax
$LN6#fib:
add eax, ecx
$LN5#fib:
add ecx, eax
$LN4#fib:
add eax, ecx
$LN3#fib:
add ecx, eax
$LN2#fib:
add eax, ecx
jmp SHORT $LN10#fib
$LN9#fib:
pop esi
ret 0
npad 1
$LN17#fib: ;jump table
DD $LN10#fib
DD $LN2#fib
DD $LN3#fib
DD $LN4#fib
DD $LN5#fib
DD $LN6#fib
DD $LN7#fib
DD $LN8#fib
_fib ENDP
Perhaps this is more applicable to situations like a linear feed back shift register, where the loop is unfolded to save shifting data between variables. For example:
while(...){
e = f(a,b,c,d);
a = b;
b = c;
c = d;
d = e;
}
is unfolded into
do{
a = f(a,b,c,d);
case 3:
b = f(b,c,d,a);
case 2:
c = f(c,d,a,b);
case 1:
d = f(d,a,b,c);
case 0:
}while(...);
and if the number of elements isn't a multiple of 4, then Duff's device is used to enter the unfolded loop.
How can I convert the following if=statement to a switch-statement WITHOUT needing to create a case for every number between that interval (41-49)? Is it possible?
if (num < 50 && num > 40)
{
printf("correct!");
}
You have to enumerate every case for a switch. The compiler converts this to a jump table, so you can't use ranges. You can, however, have multiple cases use the same block of code, which may be closer to what you want.
switch(num) {
case 41:
case 42:
case 43:
case 44:
case 45:
case 46:
case 47:
case 48:
case 49:
printf("correct!");
break;
default:
break;
}
What about this?
switch ((num-41)/9) {
case 0:
printf("correct!");
break;
}
bool criteria1 = (num < 50 && num > 40);
switch criteria1: ...
It may result in multilevel decision networks.. scary?
In C or C++ (since you are using printf, I'll assume that's what it is), cases need to be enumerated for each choice.
The only difference between switch/case and if is the possibility that the compiler can turn it into a computed goto instead of checking ranges. If switch/case supported ranges, that would defeat the purpose of opening the possibility of this optimizaton.