Namespaces
Variants

switch statement

From cppreference.net
C++ language
General topics
Flow control
Conditional execution statements
switch
Iteration statements (loops)
Jump statements
Functions
Function declaration
Lambda function expression
inline specifier
Dynamic exception specifications ( until C++17* )
noexcept specifier (C++11)
Exceptions
Namespaces
Types
Specifiers
constexpr (C++11)
consteval (C++20)
constinit (C++20)
Storage duration specifiers
Initialization
Expressions
Alternative representations
Literals
Boolean - Integer - Floating-point
Character - String - nullptr (C++11)
User-defined (C++11)
Utilities
Attributes (C++11)
Types
typedef declaration
Type alias declaration (C++11)
Casts
Memory allocation
Classes
Class-specific function properties
Special member functions
Templates
Miscellaneous

조건의 값에 따라 여러 문 중 하나로 제어를 전달합니다.

목차

구문

attr  (선택 사항) switch ( init-statement  (선택 사항) condition ) statement
attr - (since C++11) 임의의 개수의 attributes
init-statement - (since C++17) 다음 중 하나:
(since C++23)

모든 init-statement 은 세미콜론으로 끝나야 합니다. 이것이 흔히 비공식적으로 표현식이나 선언 뒤에 세미콜론이 오는 것으로 설명되는 이유입니다.

condition - 조건
statement - 문 (일반적으로 복합문)

조건

조건은 condition expression 이거나 simple declaration 일 수 있습니다.

  • 만약 문법적으로 structured binding 선언으로 해석될 수 있다면, structured binding 선언으로 해석됩니다.
(since C++26)
  • 만약 문법적으로 표현식으로 해결될 수 있다면, 표현식으로 취급됩니다. 그렇지 않으면 선언으로 취급됩니다 (이는 구조적 바인딩 선언이 아닌 선언임) (C++26부터) .

제어가 조건에 도달하면, 조건은 값을 산출하며, 이 값은 제어가 어떤 레이블로 이동할지를 결정하는 데 사용됩니다.

표현식

만약 condition 이 표현식이라면, 그것이 생성하는 값은 표현식의 값입니다.

선언

만약 condition 이 단순 선언인 경우, 이로부터 얻는 값은 결정 변수의 값입니다(아래 참조).

비구조적 바인딩 선언

선언에는 다음과 같은 제한 사항이 있습니다:

  • 구문적으로 다음 형식을 따릅니다:
  • type-specifier-seq declarator = assignment-expression
(C++11 이전)
  • attribute-specifier-seq (선택 사항) decl-specifier-seq declarator brace-or-equal-initializer
(C++11 이후)

선언의 결정 변수는 선언된 변수입니다.

구조화된 바인딩 선언

선언에는 다음과 같은 제한 사항이 있습니다:

선언의 결정 변수는 선언에 의해 도입된 e 발명 변수입니다.

(C++26부터)

타입

condition 은 다음 유형만 반환할 수 있습니다:

  • 정수형 타입
  • 열거형 타입
  • 클래스 타입

생성된 값이 클래스 타입인 경우, 컨텍스트상 정수 또는 열거형 타입으로 암시적으로 변환됩니다.

(변환된) 타입이 integral promotions 의 대상인 경우, 생성된 값은 승격된 타입으로 변환됩니다.

레이블

switch 문 내부의 모든 구문은 다음과 같은 하나 이상의 레이블로 표시될 수 있습니다:

attr  (선택 사항) case constant-expression : (1)
attr  (선택 사항) default: (2)
attr - (since C++11) 임의의 개수의 attributes
constant-expression - switch 조건의 조정된 타입으로 변환된 상수 표현식


A case 또는 default 레이블은 이를 감싸는 가장 안쪽의 switch 문과 연결됩니다.

다음 조건 중 하나라도 충족되면 프로그램의 형식이 잘못되었습니다:

  • 하나의 switch 문이 변환 후 동일한 값을 갖는 constant-expression 을 가진 여러 개의 case 레이블과 연관되어 있습니다.
  • 하나의 switch 문이 여러 개의 default 레이블과 연관되어 있습니다.

제어 흐름 전송

switch 문의 조건이 (변환될 수 있는) 값을 산출할 때:

  • 연관된 case 레이블 상수 중 하나가 동일한 값을 가지면, 제어는 일치하는 case 레이블로 표시된 문장으로 전달됩니다.
  • 그렇지 않고 연관된 default 레이블이 있는 경우, 제어는 default 레이블로 표시된 문장으로 전달됩니다.
  • 그렇지 않으면, switch 문 내의 어떤 문장도 실행되지 않습니다.

case default 레이블 자체는 제어 흐름을 변경하지 않습니다. switch 문의 중간에서 벗어나려면 break 을 참조하십시오.

컴파일러는 폴스루(fallthrough, break 없이 다음 case 또는 default 레이블에 도달하는 경우)에 대해 경고를 발생시킬 수 있습니다 단, [[ fallthrough ]] 속성이 case 레이블 바로 앞에 나타나 폴스루가 의도적임을 표시하는 경우는 제외합니다 (C++17부터) .

switch (1)
{
    case 1:
        std::cout << '1'; // "1"을 출력하고,
    case 2:
        std::cout << '2'; // 이어서 "2"를 출력함
}
switch (1)
{
    case 1:
        std::cout << '1'; // "1"을 출력
        break;            // 그리고 switch문을 종료
    case 2:
        std::cout << '2';
        break;
}

switch initializer를 포함한 switch 문

만약 init-statement 가 사용된다면, switch 문은 다음과 동일합니다:

{
init-statement
switch ( condition ) statement

}

단, init-statement 에 의해 선언된 이름들( init-statement 가 선언인 경우)과 condition 에 의해 선언된 이름들( condition 가 선언인 경우)은 동일한 스코프에 있으며, 이 스코프는 statement 의 스코프이기도 합니다.

(C++17부터)

참고 사항

제어의 이동이 변수의 범위로 진입하는 것이 허용되지 않기 때문에 , 만약 선언문이 statement 내부에서 발견되면, 이는 자체 복합문(compound statement)으로 범위가 지정되어야 합니다:

switch (1)
{
    case 1:
        int x = 0; // 초기화
        std::cout << x << '\n';
        break;
    default:
        // 컴파일 오류: default:로의 점프
        // 'x'의 범위에 초기화 없이 진입하게 됨
        std::cout << "default\n";
        break;
}
switch (1)
{
    case 1:
        {
            int x = 0;
            std::cout << x << '\n';
            break;
        } // 'x'의 스코프가 여기서 종료됨
    default:
        std::cout << "default\n"; // 오류 없음
        break;
}

키워드

switch , case , default

예제

다음 코드는 switch 문의 여러 사용 사례를 보여줍니다:

#include <iostream>
int main()
{
    const int i = 2;
    switch (i)
    {
        case 1:
            std::cout << '1';
        case 2:              // 이 case 레이블에서 실행 시작
            std::cout << '2';
        case 3:
            std::cout << '3';
            [[fallthrough]]; // 폴스루 경고를 무시하기 위한 C++17 속성
        case 5:
            std::cout << "45";
            break;           // 이후 문장들의 실행이 종료됨
        case 6:
            std::cout << '6';
    }
    std::cout << '\n';
    switch (i)
    {
        case 4:
            std::cout << 'a';
        default:
            std::cout << 'd'; // 적용 가능한 상수 표현식이 없으므로
                              // default가 실행됨
    }
    std::cout << '\n';
    switch (i)
    {
        case 4:
            std::cout << 'a'; // 아무것도 실행되지 않음
    }
    // 열거형이 switch 문에서 사용될 때, 많은 컴파일러들은
    // 열거자 중 하나가 처리되지 않으면 경고를 발생시킴
    enum color { RED, GREEN, BLUE };
    switch (RED)
    {
        case RED:
            std::cout << "red\n";
            break;
        case GREEN:
            std::cout << "green\n";
            break;
        case BLUE:
            std::cout << "blue\n";
            break;
    }
    // C++17 초기화 문법은 정수형이나 열거형 타입으로의
    // 암시적 변환이 없을 때 유용할 수 있음
    struct Device
    {
        enum State { SLEEP, READY, BAD };
        auto state() const { return m_state; }
        /* ... */
    private:
        State m_state{};
    };
    switch (auto dev = Device{}; dev.state())
    {
        case Device::SLEEP:
            /* ... */
            break;
        case Device::READY:
            /* ... */
            break;
        case Device::BAD:
            /* ... */
            break;
    }
    // 병리학적 예제들
    // 문장이 복합 문장일 필요는 없음
    switch (0)
        std::cout << "this does nothing\n";
    // 레이블들도 복합 문장을 요구하지 않음
    switch (int n = 1)
        case 0:
        case 1:
            std::cout << n << '\n';
}

출력:

2345
d
red
1

결함 보고서

다음의 동작 변경 결함 보고서들은 이전에 발표된 C++ 표준에 소급 적용되었습니다.

DR 적용 대상 게시된 동작 올바른 동작
CWG 1767 C++98 condition 의 타입이 정수 승격 대상이 아닌 경우
승격될 수 없었음
해당 타입의
condition 은 승격하지 않음
CWG 2629 C++98 condition 이 부동소수점 변수 선언일 수 있었음 금지됨

참고 항목

C 문서 에 대한 switch

외부 링크

1. Duff's Device를 사용한 루프 언롤링
2. Duff's device는 C/C++에서 코루틴 구현에 사용될 수 있음