Search

7.4 — Switch statement basics

Although it is possible to chain many if-else statements together, this is both difficult to read and inefficient. Consider the following program:

While this example isn’t too complex, x is evaluated up to three times (which is inefficient), and the reader has to be sure that it is x being evaluated each time (not some other variable).

Because testing a variable or expression for equality against a set of different values is common, C++ provides an alternative conditional statement called a switch statement that is specialized for this purpose. Here is the same program as above using a switch:

The idea behind a switch statement is simple: an expression (sometimes called the condition) is evaluated to produce a value. If the expression’s value is equal to the value after any of the case labels, the statements after the matching case label are executed. If no matching value can be found and a default label exists, the statements after the default label are executed instead.

Compared to the original if statement, the switch statement has the advantage of only evaluating the expression once (making it more efficient), and the switch statement also makes it clearer to the reader that it is the same expression being tested for equality in each case.

Best practice

Prefer switch statements over if-else chains when there is a choice.

Let’s examine each of these concepts in more detail.

Starting a switch

We start a switch statement by using the switch keyword, followed by parentheses with the conditional expression that we would like to evaluate inside. Often the expression is just a single variable, but it can be any valid expression.

The one restriction is that the condition must evaluate to an integral type (see lesson 4.1 -- Introduction to fundamental data types if you need a reminder which fundamental types are considered integral types) or an enumerated type (covered in future lesson 9.2 -- Enumerated types), or be convertable to one. Expressions that evaluate to floating point types, strings, and most other non-integral types may not be used here.

For advanced readers

Why does the switch type only allow for integral (or enumerated) types? The answer is because switch statements are designed to be highly optimized. Historically, the most common way for compilers to implement switch statements is via a Jump tables -- and jump tables only work with integral values.

For those of you already familiar with arrays, a jump table works much like an array, an integral value is used as the array index to “jump” directly to a result. This can be much more efficient than doing a bunch of sequential comparisons.

Of course, compilers don’t have to implement switches using jump tables, and sometimes they don’t. There is technically no reason that C++ couldn’t relax the restriction so that other types could be used as well, they just haven’t done so yet (as of C++20).

Following the conditional expression, we declare a block. Inside the block, we use labels to define all of the values we want to test for equality. There are two kinds of labels.

Case labels

The first kind of label is the case label, which is declared using the case keyword and followed by a constant expression. The constant expression must either match the type of the condition or must be convertible to that type.

If the value of the conditional expression equals the expression after a case label, execution begins at the first statement after that case label and then continues sequentially.

Here’s an example of the condition matching a case label:

This code prints:

Two

In the above program, x is evaluated to produce value 2. Because there is a case label with value 2, execution jumps to the statement underneath that matching case label. The program prints Two, and then the return statement is executed, which returns back to the caller.

There is no practical limit to the number of case labels you can have, but all case labels in a switch must be unique. That is, you can not do this:

The default label

The second kind of label is the default label (often called the default case), which is declared using the default keyword. If the conditional expression does not match any case label and a default label exists, execution begins at the first statement after the default label.

Here’s an example of the condition matching the default label:

This code prints:

Unknown

The default label is optional, and there can only be one default label per switch statement. By convention, the default case is placed last in the switch block.

Best practice

Place the default case last in the switch block.

Taking a break

In the above examples, we used return statements to stop execution of the statements after our labels. However, this also exits the entire function.

A break statement (declared using the break keyword) tells the compiler that we are done executing statements within the switch, and that execution should continue with the statement after the end of the switch block. This allows us to exit a switch statement without exiting the entire function.

Here’s a slightly modified example rewritten using break instead of return:

The above example prints:

Three Ah-Ah-Ah!

Best practice

Each set of statements underneath a label should end in a break statement or a return statement.

So what happens if you don’t end a set of statements under a label with a break or return? We’ll explore that topic, and others, in the next lesson.


7.5 -- Switch fallthrough and scoping
Index
7.3 -- Common if statement problems

461 comments to 7.4 — Switch statement basics

  • Xofrio

    I have a question: is there a way to write it in switch statement x < 10 || x > 20?
    I feel that there's only one option:

    And the cases are true and false, and therefore I can simply use if.
    But maybe there're other options?

  • Waldo Lemmer

    Section "Starting a switch":

    > We start a switch statement by using the switch keyword, followed by parenthesis

    Should be "parentheses"

    Section "Case labels":

    > In the above program, x is evaluated to produce value 2. Because there is a case label with value 2, execution jumps to the statement underneath that matching case label. The program prints Two, and then the return statement is exited,

    Should be "executed"

  • Chayim

    This question is mistyped

  • Chayim

    Why does this code execute to  “One Two”

    Why does it add "Two" when I dropped out the "return" after "case 1" ? Why does it add the coming case when the evaluation does not match case 2 ?

    • Chayim

      This question is addressed in the following lesson. But now my question is that if the switch function was made to match the expression so why is this function designed to compile and execute all the following cases with fallthrough ? Why not match the expression with the case matching and execute only the matching case?

      • Alex

        Because that's the way switch was originally defined. Personally I think it makes more sense to not fall through by default, but apparently the C++ standards committee doesn't think this is an important enough problem to solve to warrant additional language complexity.

  • Chayim

    Why is the switch function named "switch" ?  Is it switching something?  What is it switching?
      And why can it not replace the if else function always? When does if else work that switch does not?
      And why is switch referred as "testing for equality” ?  (To this question I think the answer is that it’s because it does not function as a Boolean only as a simple function) and not as a replacement of Boolean if else function?

    • Chayim

      The second question’s answer:

      "The one restriction is that the condition must evaluate to an integral type"

    • Alex

      I don't know the etymology behind the term "switch". A switch can only test one value and only tests for equality (meaning the value of the expression must exactly match the case value), whereas an if-else can test multiple variables and can use a wide range of comparison and logical operators.

      For example, how would you do the following using a switch?

  • frog

    Hello, thanks for the tutorials.
    On the very first example, you said that x is evaluated [three times]. Shouldn't it be [three times at most] instead? Since the execution jumps over all of the remaining chained if-else statements once it finds the condition that evaluates to true.

  • Chayim

    Why does switch function only support int and not all other variables?

  • vico

    #include<iostream>
    using namespace std;

    int main()
    {
        int price;
        float  gst;
        cout << "Enter a price: ";
        cin >> price;
        cout << "Enter amount gst: ";
        cin >> gst;
        
        switch(price)
        {
            case 90  : //how to write the value> = 90. please help me I'm stuck
              cout<<"My price is: "<< price + 0.2 * gst;
              break;
            
            case 80 ... 89 :
              cout<<"My price is: "<< price + 0.15 * gst;
              break;
              
            case 70 ... 79 :
              cout<<"My price is: "<< price + 0.1 * gst;
              break;
              
            case 60 ... 69 :
              cout<<"My price is: "<< price + 0.08 * gst;
              break;
              
            case 0 ... 59 :
              cout<<"My price is: " << price + 0.01 * gst;
              break;
            
            default:
            cout<<"wrong input " ;
            break;     
        }
    }

Leave a Comment

Put all code inside code tags: [code]your code here[/code]