switch 문(switch statement)

switch 문(switch statement)

정수 값에 따라 여러 분기 중 하나로 실행을 옮기고 싶을 때 쓰는 게 switch 문이에요. 정수 값에 따라 많은 분기 중 하나 혹은 여러 개를 실행할 때 사용해요.

출처: cppreference

본문

문법

attr-spec-seq(선택) switch ( expression ) statement
항목 의미
attr-spec-seq - (C23부터) switch 문에 적용되는 선택적 속성 목록
expression - 정수 타입의 임의의 표현식(char, 부호 있는 정수, 부호 없는 정수, 또는 열거)
statement - 임의의 문(보통 복합 문). statement 안에 case:default: 레이블이 허용되고, break; 문은 특별한 의미를 가져요.

레이블:

case constant-expression : statement (1) (C23 이전)
attr-spec-seq(선택) case constant-expression : statement(선택) (1) (C23부터)
default : statement (2) (C23 이전)
attr-spec-seq(선택) default : statement(선택) (2) (C23부터)
항목 의미
constant-expression - 임의의 정수 상수 표현식
attr-spec-seq - (C23부터) 레이블에 적용되는 선택적 속성 목록

설명(Explanation)

switch 문의 본문은 임의의 개수의 case: 레이블을 가질 수 있어요. 단, 모든 constant-expression의 값(expression의 승격된 타입으로 변환한 뒤)이 유일해야 해요. default: 레이블은 기껏해야 하나 있을 수 있어요(단, 중첩된 switch 문은 자신만의 default: 레이블이나, 감싸는 switch에서 쓰인 것과 같은 상수를 가진 case: 레이블을 쓸 수 있어요).

expression이 평가되어 그 값이 constant-expression 중 하나의 값과(expression의 승격된 타입으로 변환한 뒤) 같으면, 제어는 그 constant-expression이 레이블로 붙은 문으로 이동해요.

expression이 평가된 값이 어떤 case: 레이블과도 일치하지 않고 default: 레이블이 있으면, 제어는 default: 레이블이 붙은 문으로 이동해요.

expression이 평가된 값이 어떤 case: 레이블과도 일치하지 않고 default: 레이블도 없으면, switch 본문 중 어떤 것도 실행되지 않아요.

break 문은 statement 안 어디서 만나든 switch 문을 빠져나가요:

switch(1) {
    case 1 : puts("1"); // prints "1",
    case 2 : puts("2"); // then prints "2" ("fall-through")
}

switch(1) {
    case 1 : puts("1"); // prints "1"
             break;     // and exits the switch
    case 2 : puts("2");
             break;
}

다른 모든 선택·반복 문과 마찬가지로 switch 문은 블록 범위를 확립해요. expression에서 도입된 식별자는 문이 끝난 뒤 범위를 벗어나요.

VLA 또는 가변 수정(variably-modified) 타입의 다른 식별자가 자신의 범위 안에 case: 또는 default: 레이블을 가지면, 전체 switch 문이 그 범위 안에 있어야 해요(다시 말해 VLA는 전체 switch 이전이나 마지막 레이블 이후에 선언되어야 해요):

switch (expr)
{
        int i = 4; // not a VLA; OK to declare here
        f(i); // never called
//      int a[i]; // error: VLA cannot be declared here
    case 0:
        i = 17;
    default:
        int a[i]; // OK to declare VLA here
        printf("%d\n", i); // prints 17 if expr == 0, prints indeterminate value otherwise
}

키워드(Keywords)

switch, case, default

예제(Example)

아래 코드는 switch 문의 분기와 낙하(fall-through)가 실제로 어떻게 흐르는지 보여줘요.

#include <stdio.h>

void func(int x)
{
   printf("func(%d): ", x);
   switch(x)
   {
      case 1: printf("case 1, ");
      case 2: printf("case 2, ");
      case 3: printf("case 3.\n"); break;
      case 4: printf("case 4, ");
      case 5:
      case 6: printf("case 5 or case 6, ");
      default: printf("default.\n");
   }
}

int main(void)
{
   for(int i = 1; i < 9; ++i) func(i);
}

출력:

func(1): case 1, case 2, case 3.
func(2): case 2, case 3.
func(3): case 3.
func(4): case 4, case 5 or case 6, default.
func(5): case 5 or case 6, default.
func(6): case 5 or case 6, default.
func(7): default.
func(8): default.

case 1:case 2:break가 없어서 case 3:break까지 낙하로 계속 이어져요. case 5:는 본문이 없어 case 6:으로 바로 떨어지고, case 6:default: 사이에도 break가 없어 default까지 내려가요.

더 알아보기

  • if: 조건에 따라 분기하는 또 다른 선택 문.
  • break: switch 블록 중간에서 빠져나오는 점프 문.
  • goto: 레이블로 무조건 점프하는 문.