Skip to main content

Command Palette

Search for a command to run...

Are Switch Statements Better than If-else?

Updated
4 min read
Are Switch Statements Better than If-else?

Ever heard tech bros say, ‘switch statements are more efficient than if-else statements’? I certainly have. But have you thought of whether this is actually true? Well, is it actually true? The answer is that ‘it’s complicated!’ Let’s discuss.

While this statement has a good technical value to it, this is not always the case. Switch statements are highly optimized and can outperform regular if-else statements under specific conditions. Let’s start with the basics: what is a switch statement?

int use_if_else(int value) {
    if (value == 1) {
        return 102;
    } else if (value == 2) {
        return 15;
    } else if (value == 3) {
        return 888;
    } else if (value == 4) {
        return 42;
    } else if (value == 5) {
        return 7;
    } else {
        return 0;
    }
}

You might be familiar with the above code. This is a simple example of an if-else statement. But a switch statement for the same task looks like this:

int use_switch(int value) {
    switch (value) {
        case 1:
            return 102;
        case 2:
            return 15;
        case 3:
            return 888;
        case 4:
            return 42;
        case 5:
            return 7;
        default:
            return 0;
    }
}

But how can this be more efficient than an if-else statement? The answer is actually in the underlying assembly interpretation. Let’s compare the compiled assembly representation of the two functions.

use_if_else:
        cmp     edi, 1
        je      .L3
        cmp     edi, 2
        je      .L4
        cmp     edi, 3
        je      .L5
        cmp     edi, 4
        je      .L6
        cmp     edi, 5
        mov     eax, 0
        mov     edx, 7
        cmove   eax, edx
        ret
.L3:
        mov     eax, 102
        ret
.L4:
        mov     eax, 15
        ret
.L5:
        mov     eax, 888
        ret
.L6:
        mov     eax, 42
        ret

This is how the compiled Assembly looks like for the if-else code. Below is for the switch statement. You can see it in compiler explorer: https://godbolt.org/z/K9MzEjK77

use_switch:
        cmp     edi, 5
        ja      .L2
        mov     edi, edi
        jmp     [QWORD PTR .L4[0+rdi*8]]
.L4:
        .quad   .L2
        .quad   .L8
        .quad   .L9
        .quad   .L6
        .quad   .L5
        .quad   .L3
.L8:
        mov     eax, 102
        ret
.L6:
        mov     eax, 888
        ret
.L5:
        mov     eax, 42
        ret
.L3:
        mov     eax, 7
        ret
.L2:
        mov     eax, 0
        ret
.L9:
        mov     eax, 15
        ret

As we can see, the two codes produce completely different Assembly code. But still, both of them seem to be close to the same length. How can one be more optimized than the other? It’s all about how the code is executed. Imagine the scenario of receiving value = 5 in the if-else statement. It has to go through all the cmp and jmp instructions before we reach the value = 5 situation. But in case of the switch statement, it multiplies the value of value with 8, (because each address in the table is 8 bytes long) and jump that amount forward. Which lands us immediately at the mov and ret commands for the value of 7. This is called a ‘Jump Table’.

So, while the if-else statement was looking one after the other for the condition of value = 5, the switch statement mathematically moved execution to the 5th instruction. See below for a simplified breakdown.

if-else:
is 1 = 5? --> no, then is 2 = 5? --> no, then is 3 = 5? --> no, then is 4 = 5 no, then is 5 = 5, yes, then return 7
switch:
move 5 steps below --> return the value there

Now imagine hundreds of possible values. The execution time saved can be staggering. For those of you curious, the if-else statement gave us O(n) and the switch statement gave us O(1).

However, this is not always the case. If the conditions don’t follow a mathematical pattern, this falls apart and we don’t see much difference.

However, if you paid close attention, you see that I used a compiler flag called -fno-jump-tables in the if-else statement. This is because modern compilers are smart to identify the existence of a jump table, even in an if-else statement.

But, does this mean that it’s not useful to use a switch statement instead of the if-else? Well, not exactly. The switch statement is a lot more elegant in certain code patterns. Also, sometimes the compiler might not be able to identify the pattern and be able to optimize an if-else statement unless you use a switch statement.

In conclusion, switch statements are awesome! But still, with modern smart compilers, it is not always the case that if-else statements are bad. So next time you use an if-else statement for checking an integer, maybe consider using a switch statement.