mactro
mactro

Reputation: 518

C++ switch statement evaluation

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?

Upvotes: 0

Views: 1576

Answers (9)

abhishek_naik
abhishek_naik

Reputation: 1297

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.

Upvotes: 0

Richard Hodges
Richard Hodges

Reputation: 69854

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.

Upvotes: 1

Daniel
Daniel

Reputation: 31559

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.

Upvotes: 0

Jarod42
Jarod42

Reputation: 217075

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']();
    }
}

Upvotes: 1

lost_in_the_source
lost_in_the_source

Reputation: 11237

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.

Upvotes: 0

Slava
Slava

Reputation: 44238

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.

Upvotes: 0

Andreas DM
Andreas DM

Reputation: 10998

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.

Upvotes: 0

lorro
lorro

Reputation: 10880

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.

Upvotes: 1

πάντα ῥεῖ
πάντα ῥεῖ

Reputation: 1

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.

Upvotes: 3

Related Questions