Skip to main content

Documentation Index

Fetch the complete documentation index at: https://docs.syntblaze.com/llms.txt

Use this file to discover all available pages before exploring further.

A control flow construct that evaluates a given condition and transfers execution to a specific labeled statement based on the condition’s value. It operates via a jump table or binary search at the assembly level, providing an optimized execution path compared to sequential if-else if evaluations.

Syntax

switch (init-statement(optional) condition) {
    case constant_expression_1:
        // Statements executed if condition == constant_expression_1
        break;
    case constant_expression_2:
        // Statements executed if condition == constant_expression_2
        break;
    default:
        // Statements executed if no case matches
        break;
}
(Note: The init-statement is an optional feature introduced in C++17 and must end with a semicolon. The syntax block above uses plain text to represent the grammar template).

Technical Constraints

1. Condition Type Requirements The condition can be either an expression or a declaration of a single non-static variable with a brace-or-equals initializer. The evaluated result of the expression, or the value of the declared variable, must be of an integral type (e.g., int, char, short, long, bool), an enumeration type (enum or enum class), or a class type that is contextually implicitly convertible to exactly one integral or enumeration type. Floating-point types (float, double) and string literals/objects are strictly prohibited. 2. Case Label Requirements Every case label must evaluate to a compile-time constant expression. This includes literals, constexpr variables, and const integral variables initialized with constant expressions. All case labels within a single switch statement must have unique values after implicit conversion to the adjusted type of the condition (the type after all applicable conversions and promotions). This distinction is critical for scoped enumerations (enum class), which do not undergo integral promotion. 3. The Default Label The default label is optional and acts as a catch-all execution path if no case constant matches the evaluated condition. A switch statement may contain at most one default label, which can be positioned anywhere within the switch block, though it is conventionally placed at the end.

Execution Flow and Fallthrough

When the switch condition is evaluated, control jumps directly to the matching case label. Execution then proceeds sequentially, statement by statement. If a break statement is not encountered, execution will “fall through” into subsequent case or default blocks, ignoring their labels entirely. To explicitly indicate to the compiler that a fallthrough is intentional and to suppress compiler warnings, C++17 introduced the [[fallthrough]] attribute.
#include <iostream>

int main() {
    int value = 1;
    
    switch (value) {
        case 1:
            std::cout << "Executing Step One\n";
            [[fallthrough]]; // C++17 attribute explicitly allowing fallthrough
        case 2:
            std::cout << "Executing Step Two\n";
            break; // Terminates the switch block
    }
    
    return 0;
}

Scoping and Variable Initialization

The entire body of a switch statement constitutes a single block scope. This introduces specific rules regarding variable declarations: Jumping Over Initialization: It is ill-formed in C++ to transfer control bypassing the initialization of a variable with automatic storage duration (local variables) that has an explicit initializer or a non-trivial constructor/destructor. If such a variable is initialized inside a case, and a subsequent case is executed, control would bypass the initialization. To resolve this, variables initialized inside a case must be enclosed in their own nested block scope. Conversely, it is perfectly valid to jump over the initialization of variables with static storage duration, as their initialization is guaranteed to be handled safely by the runtime upon first execution, regardless of control flow jumps.
#include <iostream>

int main() {
    int value = 2;
    
    switch (value) {
        case 1:
            // Valid: If value == 2 or 3, control jumps over this declaration.
            // Bypassing the initialization of variables with static storage duration is permitted.
            static int y = 20; 
            std::cout << "y is " << y << '\n';
            break;
            
        case 2: {
            // Valid: Automatic variable scope is restricted to this nested block.
            // If value == 3, control jumps over this entire block, safely avoiding the bypassed initialization rule.
            int x = 10; 
            std::cout << "x is " << x << '\n';
            break;
        }
        
        case 3:
            std::cout << "Executing Step Three\n";
            break;
    }
    
    return 0;
}
Condition Declarations vs. C++17 Initialization Statement: Prior to C++17, it was already possible to declare and initialize a variable directly in the condition (e.g., switch (int x = getValue())). However, the switch logic was restricted to evaluating that specific variable. C++17 introduced the init-statement, allowing developers to declare and initialize a variable and provide a separate condition expression. Variables declared in either the init-statement or the condition are scoped strictly to the switch statement (including all case blocks) and are destroyed when the switch terminates.
#include <iostream>

struct Result {
    int statusCode;
};

Result getResult() {
    return {200};
}

int main() {
    // C++17: Separate init-statement and condition
    switch (Result res = getResult(); res.statusCode) {
        case 200:
            // 'res' is fully accessible here, but the switch evaluated 'res.statusCode'
            std::cout << "Success. Status Code: " << res.statusCode << '\n';
            break;
        case 404:
            std::cout << "Not Found. Status Code: " << res.statusCode << '\n';
            break;
    }
    
    return 0;
}
Master C++ with Deep Grasping Methodology!Learn More