0

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?

mactro
  • 518
  • 7
  • 13
  • Following statements are also evaluated, until they meet a `break;` statement or fall off the switch statement. – abhishek_naik Jun 24 '16 at 13:34
  • It's not clear what you're asking. The cases are constant expressions, and it does not make one bit of difference whether those constant expressions are evaluated. Are you asking if `currentChar` is compared to those case values? Are you asking if `doSomething()` is evaluated? Or are you asking something else? –  Jun 24 '16 at 13:36
  • You can test each way and find out yourself. Generally Which way is faster questions are too broad as they can depended on many different factors. – NathanOliver Jun 24 '16 at 13:36
  • @hvd I'm asking if the `currentChar` is compared to those case values. – mactro Jun 24 '16 at 13:43
  • @mactro Okay. So you know that `doSomething()` will be called, and you're wondering, when `currentChar == 'G'`, if `currentChar == 'T'`, `currentChar == 'M'`, `currentChar == ';'`, etc. are pointlessly evaluated just to ignore their results. Is that right? In that case, the very first answer you got (@πάνταῥεῖ's) probably covers it. –  Jun 24 '16 at 13:51

9 Answers9

3

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.

πάντα ῥεῖ
  • 1
  • 13
  • 116
  • 190
1

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.

lorro
  • 10,687
  • 23
  • 36
1

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']();
    }
}
Jarod42
  • 203,559
  • 14
  • 181
  • 302
  • Hi what do you mean by "_comparison is not necessary sequential. _" and could you please provide a basic design of a jump table? –  Jun 24 '16 at 13:43
1

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.

Richard Hodges
  • 68,278
  • 7
  • 90
  • 142
0

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.

Community
  • 1
  • 1
abhishek_naik
  • 1,287
  • 2
  • 15
  • 27
  • break there is needed, not for proper compilation though. – Slava Jun 24 '16 at 14:07
  • @Slava sorry, could you be more specific? – abhishek_naik Jun 24 '16 at 15:31
  • it is better to put `break` into last statement, on one side compiler will ignore that, on another - when you add another label after the last one you will not get surprises. IE it is too easy to create a bug when there is no break. – Slava Jun 24 '16 at 15:34
0

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.

Andreas DM
  • 10,685
  • 6
  • 35
  • 62
0

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.

Slava
  • 43,454
  • 1
  • 47
  • 90
0
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.

lost_in_the_source
  • 10,998
  • 9
  • 46
  • 75
0

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.

Daniel
  • 30,896
  • 18
  • 85
  • 139
  • `a || b` is short circuiting and guaranteed to not evaluate `b` if `a` evaluated to true (unless you overload it of course). `5.15 [expr.log.or]` – user975989 Jun 24 '16 at 14:08
  • @user975989: as I said, if a and b have no side effects, the as-if rule allows the compiler to implement the operator in any way that produces the same result – Daniel Jun 24 '16 at 14:30