5.3 — Switch statements

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

Because doing if-else chains on a single variable testing for equality is so common, C++ provides an alternative conditional branching operator called a switch. Here is the same program as above in switch form:

The overall idea behind switch statements is simple: the switch expression is evaluated to produce a value, and each case label is tested against this value for equality. If a case label matches, the statements after the case label are executed. If no case label matches the switch expression, the statements after the default label are executed (if it exists).

Because of the way they are implemented, switch statements are typically more efficient than if-else chains.

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 the expression that we would like to evaluate. Typically this expression is just a single variable, but it can be something more complex like nX + 2 or nX - nY. The one restriction on this expression is that it must evaluate to an integral type (that is, char, short, int, long, long long, or enum). Floating point variables, strings, and other non-integral types may not be used here.

Following the switch 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. A constant expression is one that evaluates to a constant value -- in other words, either a literal (such as 5), an enum (such as Color::red), or a constant variable (such as x, when x has been defined as a const int).

The constant expression following the case label is tested for equality against the expression following the switch keyword. If they match, the code under the case label is executed.

It is worth noting that all case label expressions must evaluate to a unique value. That is, you can not do this:

It is possible to have multiple case labels refer to the same statements. The following function uses multiple cases to test if the ‘c’ parameter is an ASCII digit.

In the case where c is an ASCII digit, the first statement after the matching case statement is executed, which is “return true”.

Note that you don’t need to use “break” if you use “return” (and vice versa), as either will cause the switch to terminate.

The default label

The second kind of label is the default label (often called the “default case”), which is declared using the default keyword. The code under this label gets executed if none of the cases match the switch expression. The default label is optional, and there can only be one default label per switch statement. It is also typically declared as the last label in the switch block, though this is not strictly necessary.

In the isDigit() example above, if c is not an ASCII digit, the default case executes and returns false.

Switch execution and fall-through

One of the trickiest things about case statements is the way in which execution proceeds when a case is matched. When a case is matched (or the default is executed), execution begins at the first statement following that label and continues until one of the following termination conditions is true:
1) The end of the switch block is reached
2) A return statement occurs
3) A goto statement occurs
4) A break statement occurs
5) Something else interrupts the normal flow of the program (e.g. a call to exit(), an exception occurs, the universe implodes, etc…)

Note that if none of these termination conditions are met, cases will overflow into subsequent cases! Consider the following snippet:

This snippet prints the result:


This is probably not what we wanted! When execution flows from one case into another case, this is called fall-through. Fall-through is almost never desired by the programmer, so in the rare case where it is, it is common practice to leave a comment stating that the fall-through is intentional.

Break statements

A break statement (declared using the break keyword) tells the compiler that we are done with this switch (or while, do while, or for loop). After a break statement is encountered, execution continues with the statement after the end of the switch block.

Let’s look at our last example with break statements properly inserted:

Now, when case 2 matches, the integer 2 will be output, and the break statement will cause the switch to terminate. The other cases are skipped.

Warning: Forgetting the break statement at the end of the case statements is one of the most common C++ mistakes made!

Multiple statements inside a switch block

With if statements, you can only have a single statement after the if-condition, and that statement is considered to be implicitly inside a block:

However, with switch statements, you are allowed to have multiple statements after a case label, and they are not considered to be inside an implicit block.

In the above example, the 4 statements between the case label and default label are part of case 1, but not considered to be inside an implicit block.

If this seems a bit inconsistent, it is.

Variable declaration and initialization inside case statements

You can declare (but not initialize) variables inside the switch, both before and after the case labels:

Note that although variable y was defined in case 1, it was used in case 2 as well. Because the statements under each case are not inside an implicit block, that means all statements inside the switch are part of the same scope. Thus, a variable defined in one case can be used in another case, even if the case in which the variable is defined is never executed!

This may seem a bit counter-intuitive, so let’s examine why. When you define a local variable like “int y;”, the variable isn’t created at that point -- it’s actually created at the start of the block it’s declared in. However, it is not visible (in scope) until the point of declaration. The declaration statement doesn’t need to execute -- it just tells the compiler that the variable can be used past that point. So with that in mind, it’s a little less weird that a variable declared in one case statement can be used in another cases statement, even if the case statement that declares the variable is never executed.

However, initialization of variables directly underneath a case label is disallowed and will cause a compile error. This is because initializing a variable does require execution, and the case statement containing the initialization may not be executed!

If a case needs to define and/or initialize a new variable, best practice is to do so inside a block underneath the case statement:


If defining variables used in a case statement, do so in a block inside the case (or before the switch if appropriate)

Quiz time

Question #1

Write a function called calculate() that takes two integers and a char representing one of the following mathematical operations: +, -, *, /, or % (modulus). Use a switch statement to perform the appropriate mathematical operation on the integers, and return the result. If an invalid operator is passed into the function, the function should print an error. For the division operator, do an integer division.

Hint: “operator” is a keyword, variables can’t be named “operator”.

Show Solution

Question #2

Define an enum class named Animal that contains the following animals: pig, chicken, goat, cat, dog, ostrich. Write a function named getAnimalName() that takes an Animal parameter and uses a switch statement to return the name for that animal as a std::string. Write another function named printNumberOfLegs() that uses a switch statement to print the number of legs each animal walks on. Make sure both functions have a default case that prints an error message. Call printNumberOfLegs() from main() with a cat and a chicken. Your output should look like this:

A cat has 4 legs.
A chicken has 2 legs.

Show Solution

5.4 -- Goto statements
5.2 -- If statements

425 comments to 5.3 — Switch statements

  • yup

    On the second quiz question, I tried using enum class instead of an enum. My compiler is C++11 compatible. It wasn't working for me, so I just decided to copy and paste the whole solution into my program to see if I could change it to enum class and see what would happen. Every subsequent use of something from the Animal enum class is "undefined" according to my compiler. How did changing it from enum to enum class make it undefined in all subsequent uses in the program? Did I just forget how enum classes work?

    • Alex

      Enum classes put enumerators in the scope of the enumeration. So if you change enum to enum class, then all enumerators need to be updated to use an Animal:: prefix.

  • rockstar_joe

    Hi, could someone tell me, if this code is allright? I used a struct for all user inputs and an enumeration for input states (good input / wrong input).
    It worked for me.

    • nascardriver


      You have repeated code in line 39, 45, ...
      You can fix that by doing only the calculation in the switch, then print after the switch. You can't use temp.baseOperator to print the operator. The rest looks good :)

  • Friedrich

    Isn't working but I don't know why

    • nascardriver

      Which errors/warnings are you getting?
      What's happening?
      What did you expect to happen?
      What have you done to try to solve it?

    • fxr

      Friedrich if you're still wondering why it doesn't work its because you have the y and the z in the wrong place you have it like this
      calculateResult(x, y, z)
      while it should be like this
      calculateResult(x, z, y)
      you're passing off the wrong values to the variables in the function

  • iReallyApreciateThisSiteGoodJob

    You mention this:

    "However, initialization of variables directly underneath a case label is disallowed and will cause a compile error. This is because initializing a variable does require execution, and the case statement containing the initialization may not be executed!"

    This implies that there is a situation inside a switch statement's block where initialization of variables is allowed, but i can't seem to find information on where it is allowed.

    Sorry if im misinterpreting it.

  • Dhruv Patwa

    I tried doing the calculator problem given in this tutorial using struct.The program is running but not giving expected results by operators, Eg.It may show 2+3=1589432.I tried a lot but could not spot the problem in the code . could you please help me out.Here is my code

    thanks in advance.

    • nascardriver

      Line 12, 14: Those '\n' don't do anything, remove them.
      Line 25 and 27 never run, you're using uninitialized variables. Define `x` and `y` before the `switch` or use `values.integer` directly.

      Make sure you enabled compiler warnings. You compiler should have warned you about both issues.

      • Dhruv Patwa

        yeah it worked! thanks. But I could still not understand what was the problem if i am defining the variables inside switch .

        • nascardriver

          Nothing outside of cases gets executed.

          This program doesn't print anything. Line 24-27 in your code never ran. You are allowed to declare variables outside of cases, but they won't be initialized.

  • Is it bad practice to put the case conditions in brackets like a so:


  • ayush jain

    but, since variables are created when the block begins why can not be intialized then only and be in scope after its declaration ..

  • Vova

    Hi there,
    In the examle concerning case labels I spotted a semicolon at the end:

    switch (x)
        case 4:
        case 4:  // illegal -- already used value 4!
        case COLOR_BLUE: // illegal, COLOR_BLUE evaluates to 4!
    };                                                              <-- this one

    Is it necessary?

  • The "Case" statement makes the programs really easy!! I performed such a program of "Weekdays" by using CASE!

  • hellmet

    Why is this a compile error? I don't see a reason why C++ doesn't allow this? I mean the 'int k' is in the switch's block right?

    • `k` is visible in `case 1`, but the initialization of `k` is never performed. Control flow jumps from line 1 to line 8, ignoring everything in between. If you were to access `k` in `case 1`, it'd cause undefined behavior, because `k` is uninitialized.

      `a` is legal, because it doesn't have an initializer. It's immediately obvious that accessing `a` without writing first causes undefined behavior.

      `y` is legal for the same reason as `a`. `y` is accessible to all cases after `case 1`, but it's uninitialized. It's only `4` if `case 1` was matched and fell through.

      • hellmet

        I'm just confused as to why C++ would allow declaration but not definition in the block. I assumed that since the compiler can 'allocate space', why can't it just assign the value in the binary (I tried it with uniform initialization too)?

        • > I'm just confused as to why C++ would allow declaration but not definition in the block.

          Prints "3", right? No. This would be extremely confusing, so it's illegal. If a variable has an initializer, we should be safe to assume that the variable gets initialized. Variables get initialized when their definition is reached. `switch` is just a bunch of labels, all in the same scope. `x` is visible in the scope of the case, but control flow never reached `x` so it was never initialized.

          > why can't it just assign the value in the binary
          The value might be unknown at compile-time.
          The initialization might depend on something else to run first.

          If you need a variable in the `switch`'s scope, define it in the `switch`'s header.

  • DD-Hash

    Why is Using range in switch case in C/C++  not mentioned here. We can easily rewrite isDigit(char c) code above using ' ... '.

  • nibar

    Maybe this is already in the lesson but if not. You should include that switch statements can't be used with strings. Tried it on question2 and realised it didn't work so had to look at the answer to question 2.

  • Johnnie Rando

    Just the function (practicing using headers and .cpp files)
    What would be the difference in declaring/initializing int x, y and char z in the function parameters versus within the function itself, like I have it?  

    • You decreased reusability. Now you can't use `calculate` with values that came from somewhere else, they'll always be requested from the user.

      - Line 16 is useless, you're validating the operator in the `switch`-statement.
      - `calculate`'s return value is unused. Declare it `void`.

    • Johnnie Rando

      Thank you for the prompt reply. I was guessing it was something along the lines of re-application of the calculate statement. So my 'if' statement is just doing what the default statement within the switch statement is doing? Okay gotcha. Thank you for the help.

  • learning

    Any suggestions? (Question #1):

    And this is for question #2:

    • - If your program prints anything, the last thing it prints should be a line feed.
      - Use single quotation marks for characters ('2' instead of "2").

      Both solutions looks good otherwise, I like your name style :-)

  • Sam

    Here is my solution for Question #2.

  • Benur21

    What about using break; in the default case?

    • Sam

      The break; statement isn't required to be used in the default case. You can use it if you feel satisfied doing so, but it isn't required.

      • The `default` case doesn't have to be the last case.

        The last case doesn't need a `break`, but it should be added to allow the cases to be shuffled.

  • Parsa

    When using the modulus operator, both the operands must be an integral type.

    So I used static_cast to turn the operands from a double to an int (they were a double) but the compiler still gives me an error and tells me that the operands are still of type double.

  • Phuong

    I have a question in your code. I don't think the command line std :: cout in main () can be used to export the command line std :: cout in calculator (), which will cause an error, but I don't understand why on my machine at times Show this error, sometimes not, please help me?

    /#include <iostream>

    int calculate(int x, int y, char op)
        switch (op)
            case '+':
                return x + y;
            case '-':
                return x - y;
            case '*':
                return x * y;
            case '/':
                return x / y;
            case '%':
                return x % y;
                std::cout << "calculate(): Unhandled case\n";
                return 0;

    int main()
        std::cout << "Enter an integer: ";
        int x;
        std::cin >> x;

        std::cout << "Enter another integer: ";
        int y;
        std::cin >> y;

        std::cout << "Enter a mathematical operator (+, -, *, /, or %): ";
        char op;
        std::cin >> op;

        std::cout << x << " " << op << " " << y << " is " << calculate(x, y, op) << "\n";

        return 0;

  • SamiraFerdi

    Hi, Alex and Nascardriver! This is my code for quiz no.2.
    I think it's more readable if getAnimalName() is void type than Alex did. What do you think?
    Second, I think function call getAnimalName() inside printNumberOfLegs() make function less modular and less independent. What do you think?

    • `getAnimalName` doesn't get an animal's name anymore, it prints it. The function name should be adjusted, eg. to `printAnimalName`. Same for `printNumberOfLegs`.
      You're right, your code is less modular.
      The code looks good otherwise!

  • BP

    I have a question about the first solution, or rather a question about my solution.

    The way I'm getting the inputs I know can enter the sum direct as 1+1 or 34%6 and it takes the seperate number/chars to the right variable.

    I was just wondering if this is the smart thing to do, are there downsides with this take?
    Are there better ways to do this?


    • Hi!

      - You'll learn about good alternatives to `exit` later, until then, use `std::exit`.
      - Inconsistent formatting. Use your editor's auto-formatting feature.
      - "printNumberOfLegs" is a bad name, the function doesn't print the number of legs.
      - There's no need to manually set `Animal::COW`.

  • noobmaster

    In your example of multiple cases

    no break after return true?

  • hiep

    my issue is whenever I execute my program with num2=0 and choose division option, i will get the statement " cant do the operation because num2 = 0\n" but after that I also get a sequence of number like 26900(something else). Can anyone one explain why to me ? thank you

  • This is a nice post. I have no idea how to create the swich statement in c++ but after reading this post I really got the solution. Thanks for this post. Thanks!!


    it was very interesting!! static_cast....


    the default row of switch in both of two functions, not possible to execute. I have to send wrong animal but compiler has stop me. so how to send wrong animal to active default of switch?
    it is possible if we have a wrong member in enum. like car.
    Is that right?


    hello and thank you.
    please your advice.
    thank's again.

    • * Line 21, 31: Don't pass 32767 to @std::cin.ignore. Pass @std::numeric_limits<std::streamsize>::max().
      * Your forward declarations can be prevented by moving @main below the other functions.
      * Declare 1 variable per line.
      * @retCode should be a bool.
      * Line 17+: Should be do-while.

  • This post is really good I also beginner in the coding world so I have no idea about c++, I also tried to create switch statement but after reading this post I get an idea how to write switch statement without facing an error.

  • Gav

    I confused myself so much, finally realised in the Animals struct I had put string name;
    instead of using AnimalType Type;

    After 30 mins of swearing at myself, I realised and felt so dumb ha ha.

    Is this okay?

    Sorry the formatting messed up while copying it over, but I'm too lazy to adjust it , it's not too bad haha.

    • * Don't use "using namespace", it can lead to name collisions.
      * Line 36, 37: Initialize your variables with brace initializers.

      > realised in the Animals struct I had put string name
      Nope, there's not supposed to be a struct in this quiz.

Leave a Comment

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