C언어 | switch 문

CHOI·2021년 6월 3일
0

C 언어

목록 보기
10/28
post-thumbnail

이번에는 if문의 친구인 switch 문에 대해서 알아보자.

이 친구가 if의 친구인 이유는 그만큼 if문과 정말 비슷하기 때문이다. 아래의 간단한 강아지 시뮬레이션을 보자.

#include <stdio.h>
int main() {
  int input;

  printf("마이펫 \n");
  printf("무엇을 하실 것인지 입력하세요 \n");
  printf("1. 밥주기 \n");
  printf("2. 씻기기 \n");
  printf("3. 재우기 \n");

  scanf("%d", &input);

  if (input == 1) {
    printf("아이 맛있어 \n");
  } else if (input == 2) {
    printf("아이 시원해 \n");
  } else if (input == 3) {
    printf("zzz \n");
  } else {
    printf("무슨 명령인지 못 알아 듣겠어. 왈왈 \n");
  }
  return 0;
}
마이펫
무엇을 하실 것인지 입력하세요
1. 밥주기
2. 씻기기
3. 재우기
1
아이 맛있어

위와 같이 3가지의 명령어에 따라서 반응하고 알 수 없는 명령어의 경우 "무슨 명령인지 못 알아 듣겠어. 왈왈"

를 출력한다고 해보자. 그런데 만약 여기서 명령어를 10개로 늘린다면 어떨까? 아니면 100개가 늘어난다면??

if (...) {
  ...
} else if (...) {
  ...
} else if (...) {
  ...
} else if (...) {
  ...
} else if (...) {
  ...
} else if (...) {
  ...
} else if (...) {
  ...
} else if (...) {
  ...
} else if (...) {
  ...
} else if (...) {
  ...
}

이런식으로 계속 코드를 작성해야할 것이다. 이러면 보는 사람도 불편하고 작성하는 사람도 힘들다.

이럴 때 사용하는 것이 마로 switch 이다. 위와 같이 동일한 변수에 대한 비교문이 반복될때 사용한다.

#include <st될dio.h>
int main() {
  int input;

  printf("마이펫 업그레이드\n");
  printf("무엇을 하실 것인지 입력하세요 \n");
  printf("1. 밥주기 \n");
  printf("2. 씻기기 \n");
  printf("3. 재우기 \n");

  scanf("%d", &input);

  switch (input) {
    case 1:
      printf("아이 맛있어 \n");
      break;

    case 2:
      printf("아이 시원해 \n");
      break;

    case 3:
      printf("zzz \n");
      break;

    default:
      printf("무슨 명령인지 못 알아 듣겠어. 왈왈 \n");
      break;
  }

  return 0;
}

여기서 주의해야할 점.

switch 문에 사용될 변수로는 반드시 정수 데이터를 보관하면 변수여야 한다. 다시말해서 '변수' 부분에 들어가는 변수들의 타입은 char , short , int , long 중에 하나여야 한다. 만약 위 코드의 input 자리에 floatdouble 가 들어가면 오류가 발생한다.

변수 == 1일 때 가장 맨 위의 case가 실행이 되는데 print문이 실행되고 나서 break; 가 실행이 되어야 swith 문을 빠져나간다. 만약 변수 == 2 라면 앞서 다른 case는 넘어가고 case 2 가 실행이 된다. 만약 break 를 작성하지 않는다면 아래와 같이 실행된다.

마이펫 업그레이드
무엇을 하실 것인지 입력하세요 
1. 밥주기 
2. 씻기기 
3. 재우기
1
아이 맛있어 
아이 시원해 
zzz 
무슨 명령인지 못 알아 듣겠어. 왈왈

case 1이 실행이 되었지만 break로 swtich문을 빠져나오지 못하여 아래 case까지 줄줄이 실행되는 것이다.

여기서 또 주의해야할 점

'값' 의 위치하는 것들은 모두 상수 이여야한다. 만약 값 부분에 변수가 들어오면 오류가 발생한다.(이유는 아래 쪽에 설명 되어 있다.)

그리고 마지막에 default 는 if 문에서 else 와 같은 역할을 한다. 이도저도 아닌 값이면 실행되는 구문이다.


#include <stdio.h>
int main() {
  char input;

  printf("(소문자) 알파벳 읽기\n");
  printf("알파벳 : ");

  scanf("%c", &input);

  switch (input) {
    case 'a':
      printf("에이 \n");
      break;

    case 'b':
      printf("비 \n");
      break;

    case 'c':
      printf("씨 \n");
      break;

    default:
      printf("죄송해요.. 머리가 나빠서 못 읽어요  \n");
      break;
  }

  return 0;
}
(소문자) 알파벳 읽기
알파벳 : b
비

사실 아까 위에서 switch 문은 정수데이터만 처리한다고 했었는데 위의 예시를 보면 문자데이터도 들어간다.

왜 문자 데이터가 들어가도 처리가 될까?

만약 의문이 쉽게 해결하셨다면 복습을 잘한 사람일 것이다. 왜냐하면 컴퓨터는 저번에 배웠듯이 문자와 숫자를 구분하지 못한다.( 문자 입력 받기 )

컴퓨터는 모든 문자를 숫자로 처리한 다음에 우리에게 보여줄 때만 문자로 보여준다. 따라서 문자 = 숫자 라고 해도 무방하다.


이쯤 되면 의문이 하나가 생긴다.

정말로 switch 가 필요한 것인가? if-else 로도 다 해결할 수 있는데 굳이 겉으로 보기에 깔끔하게 보인다고 switch 를 사용해야하는 것인가? 내부적으로 switchif-else 가 차이가 없는 것인가?

매우 훌륭한 질문이다. 자세히 이해하기 위해선 어셈블리어의 대한 이해가 필요하다(https://blog.naver.com/kki2406/80041410085) 에서 자세히 볼 수 있다.

위 링크를 통해 이해한다면 더할나위 없지만 간단하게 설명을 해보자면


위의 사진은 같은 소스 코드를 ifswitch 에 대해서 나타낸 것이다. 사실 외형적으로 처리하는데에는 별 차이가 없다. 단지 내부적으로 어떻게 처리되냐가 다를 뿐이다.

먼저 if 문은 각 경우의 값들을 다 비교한다. 여기선 3번 비교한다. if 일때 1번, else if 일떄 2번, else 일때 비교 없이 자동으로 처리되므로 3번.

if 문은 case 에 대해서 값을 비교하므로 최악의 경우 모든 case 에 대해서 값을 비교하는 연산(어셈블리어에서 CMP 연산)을 하게 된다.

그런데 switch 문에서는 사뭇 다르다. switch의 경우 내부적으로 jump table 이라는 것을 생성하는데 이때 case의 값에 따라서 jump table의 크기가 달라진다. 예를들의 case :1~ case: 10 까지 있다면 jump table에는 0부터 9까지 들어가게 된다. 여기서 우리가 앞서 case : 값 에서 값부분에 변수를 넣으면 왜 안되는지 이유를 알 수 있다. jump table은 프로그램 초기에 작성되기 때문에 '값' 부분에 변수가 오면 jump table에서 무엇이 올지 알 수 없으므로 변수를 사용하면 안된다.

이 값들은 무엇을 의미하면 각 case 별로 명령들이 위치한 곳의 주소를 가리키게 된다. 만약 1 인 지점으로 점프하게 되면 "아이 시원해"가 나오고 0 인 지점으로 점프하면 "아이 맛있어"가 나오게 된다. 이제, 변수값에 따라 변수가 3이면 jump table의 3 번째 원소를 찾아서 그 값에 해당되는 곳으로 점프하게 된다.

(실제로 switch 문의 처리과정은 이보다 더 복잡하나 쉽게 설명한 것이다)

따라서 switch 를 사용하면 case에 따라서 CMP연산이 늘어나는 것이 아니라 jump table의 크키만 커질 뿐 성능에는 전혀 영향을 받지 않게 된다.

결론적으로 말하자면 switch 를 효과적으로 처리되기 위해선 case 의 '값'이 그리 크지 않고, '값'들이 순차적으로 정렬되어 있고, 그 '값' 들의 차이가 크지 않다면 최고의 효율적인 switch 를 사용할 수 있다.

profile
벨로그보단 티스토리를 사용합니다! https://flight-developer-stroy.tistory.com/

0개의 댓글