티스토리 뷰
안녕하세요, IT디자이너입니다.
이번 포스팅은 switch문의 오해와 진실에 관하여 포스팅하도록 하겠습니다.
여러분들은 조건문을 사용할 때 switch문과 if문중 어떤 것을 주로 사용하시나요?
필자는 대개 if문을 사용하는 개발자를 많이 보았습니다. if문을 주로 사용하시는 분들께 이유를 물어볼 경우
switch문은 보기가 불편하거나 쓰기가 번거롭다 또는 switch문은 성능이 떨어진다는 답변을 듣곤 하였습니다.
하지만 이번 포스팅으로 switch문의 오해에 대하여 확실히 풀어드리도록 하겠습니다.
1. if 문 사용
#include <stdio.h>
int main()
{
int num = 4;
if (num == 0)
printf_s("0을 선택하였습니다.");
else if (num == 1)
printf_s("1을 선택하였습니다.");
else if (num == 2)
printf_s("2를 선택하였습니다.");
else if (num == 3)
printf_s("3을 선택하였습니다.");
else if (num == 4)
printf_s("4를 선택하였습니다.");
}
if문 사용 시 어셈블리어
if (num == 0)
0045108B cmp dword ptr [num],0 // 첫 번째 비교
if (num == 0)
0045108F jne main+20h (04510A0h) // 제로 플레그 확인 후 점프
printf_s("0을 선택하였습니다.");
00451091 push 453068h
00451096 call printf_s (0451040h)
0045109B add esp,4
0045109E jmp main+72h (04510F2h)
else if (num == 1)
004510A0 cmp dword ptr [num],1 // 두 번째 비교
004510A4 jne main+35h (04510B5h) // 제로 플레그 확인 후 점프
printf_s("1을 선택하였습니다.");
004510A6 push 453054h
004510AB call printf_s (0451040h)
004510B0 add esp,4
004510B3 jmp main+72h (04510F2h)
else if (num == 2)
004510B5 cmp dword ptr [num],2 //세 번째 비교
004510B9 jne main+4Ah (04510CAh) // 제로 플레그 확인 후 점프
printf_s("2를 선택하였습니다.");
004510BB push 453040h
004510C0 call printf_s (0451040h)
004510C5 add esp,4
004510C8 jmp main+72h (04510F2h)
else if (num == 3)
004510CA cmp dword ptr [num],3 // 네 번째 비교
004510CE jne main+5Fh (04510DFh) // 제로 플레그 확인 후 점프
printf_s("3을 선택하였습니다.");
004510D0 push 45302Ch
004510D5 call printf_s (0451040h)
004510DA add esp,4
004510DD jmp main+72h (04510F2h)
else if (num == 4)
004510DF cmp dword ptr [num],4 // 다섯 번째 비교
004510E3 jne main+72h (04510F2h) // 제로 플레그 확인 후 아래 코드 실행
printf_s("4를 선택하였습니다.");
004510E5 push 453018h
004510EA call printf_s (0451040h)
004510EF add esp,4
위의 코드는 if문 소스코드에 해당되는 어셈블리코드입니다.
if문을 사용 시 해당 하는 값이 나올 때 까지 cmp연산을 통하여 하나 하나 비교 후 제로플레그가 0이 아닌 값이 나올 때 까지 비교합니다.
만약 if문 조건에 맞는 값이 마지막에 있다면 불필요한 cmp 연산과 jne 연산을 진행하게됩니다.
2. switch 문 사용
switch문과 switch문에 해당하는 어셈블리어입니다.
#include <stdio.h>
int main()
{
int num = 4;
switch (num) {
case 0:
printf_s("0을 선택하였습니다.");
break;
case 1:
printf_s("1을 선택하였습니다.");
break;
case 2:
printf_s("2를 선택하였습니다.");
break;
case 3:
printf_s("3을 선택하였습니다.");
break;
case 4:
printf_s("4를 선택하였습니다.");
}
}
int num = 4;
005C1086 mov dword ptr [num],4
switch (num) {
005C108D mov eax,dword ptr [num]
005C1090 mov dword ptr [ebp-4],eax
005C1093 cmp dword ptr [ebp-4],4 // num값과 마지막 case문을 비교합니다.
005C1097 ja $LN8+0Dh (05C10ECh) //앞의 값이 클 경우 switch문을 벗어납니다.
005C1099 mov ecx,dword ptr [ebp-4] // ecx레지스터에 값을 넣습니다.
005C109C jmp dword ptr [ecx*4+5C10F4h] // 해당하는 값을 switch 테이블에 접근합니다.
case 0:
printf_s("0을 선택하였습니다.");
005C10A3 push 5C3068h
005C10A8 call printf_s (05C1040h)
005C10AD add esp,4
break;
005C10B0 jmp $LN8+0Dh (05C10ECh)
case 1:
printf_s("1을 선택하였습니다.");
005C10B2 push 5C3054h
005C10B7 call printf_s (05C1040h)
005C10BC add esp,4
break;
005C10BF jmp $LN8+0Dh (05C10ECh)
case 2:
printf_s("2를 선택하였습니다.");
005C10C1 push 5C3040h
005C10C6 call printf_s (05C1040h)
005C10CB add esp,4
break;
005C10CE jmp $LN8+0Dh (05C10ECh)
case 3:
printf_s("3을 선택하였습니다.");
005C10D0 push 5C302Ch
005C10D5 call printf_s (05C1040h)
005C10DA add esp,4
break;
005C10DD jmp $LN8+0Dh (05C10ECh)
case 4:
printf_s("4를 선택하였습니다.");
005C10DF push 5C3018h
005C10E4 call printf_s (05C1040h)
005C10E9 add esp,4
}
}
switch문의 어셈블리 코드를 보시면, 마지막 case문의 값 과 num 값을 비교 후 num의 값이 case를 벗어난다면,
case문을 거치지 않고 switch문을 벗어나며, num의 값이 case문 이내의 값일 경우 switch 테이블에 접근하여 해당하는 case에 바로 접근합니다.
여기서 switch 테이블이란? 컴파일러가 생성한 case문을 위한 메모리공간 즉, 배열이라고 생각하시면 됩니다.
메모리 연산으로 접근하기 때문에 하나하나 비교할 필요없이 조건에 맞는 case문에 접근이 가능합니다.
하지만!!!! case가 5,15,30,100 처럼 일정하지 않고 뒤죽박죽일 경우 switch 테이블은 생성되지 않아
일정한 순서의 case보다 성능이 훨씬 떨어지게 됩니다.
이렇게 switch문과 if문의 차이를 확인하였으며, switch의 case가 일정할 경우 if문 보다 훨씬 뛰어난 성능을 발휘하며,
switch문은 확실한 가시성 덕분에 유지보수성이 조금 더 뛰어나다고 생각됩니다.
이상 IT디자이너였습니다.
감사합니다.
'Language > C 언어' 카테고리의 다른 글
C언어의 문자 & 문자열 함수!! (표준 입출력 함수-1) (0) | 2020.03.28 |
---|---|
C언어 구조체의 숨겨진 특징 (0) | 2020.03.27 |
C언어 열거형의 정의와 의미 (0) | 2020.03.25 |
C/C++ 함수의 호출 규약 (Calling Convention) with 어셈블리 (1) | 2020.03.24 |
C/C++언어의 비트연산자 사용방법 및 활용 용도 (1) | 2020.03.20 |
- Total
- Today
- Yesterday
- C언어 #C++ #어셈블리어 #열거형 데이터타입 #IT디자이너
- IT디자이너 #QuickSort #퀵정렬 #C언어 #C++ #자료구조 #알고리즘
- C언어 #C++ #IT디자이너
- C언어 #C++ #어셈블리어 #재귀함수 #IT디자이너
- C언어 #자료구조 #C++ #연결리스트 #리스트 #알고리즘 #IT디자이너
- C언어 #C++ #파일 입출력 #텍스트파일 #IT디자이너
- C언어 #C++ #구조체 정렬 #pragma #IT디자이너
- C언어 #C++ #어셈블리어 #함수 호출 규약 #IT디자이너 #비쥬얼 스튜디오 #IT
- 스택 #자료구조 #Stack #IT디자이너 #알고리즘 #C언어 #스택 과제 #C++
- C언어 #C++ #삼각함수 #IT디자이너 #문제풀이 #2진수 #16진수 #비트 #bit #비트연산자
- C언어 #스트림 #버퍼링 #표준 입출력 함수 #C++언어 #IT디자이너
- C언어 #C++ #어셈블리어 #구조체 #구조체 특징 #IT디자이너
- 어셈블리어 #IT디자이너 #C언어 #C++언어 #어셈블리 #어셈블러
- C언어 #C++ #시간 함수 #타이밍 맞추기 #timer interrupt #IT디자이너
- IT디자이너 #C언어 #C++ #IT디자이너 #코딩테스트
- C언어 #C++ #캐시hit #캐시라인 #캐시무효화
- C언어 #포인터 #IT디자이너
- C언어 #C++ #switch #if #어셈블리어 #switch문 사용 이유 #IT디자이너
- Debug #C언어 #C++ #비쥬얼스튜디오 #Release #IT
- C언어 #포인터 #배열 포인터 #포인터 배열 #함수
- C언어 #C++ #어셈블리어 #IT디자이너 #비트연산자 #연산자 #C언어의 비트 연산자
- C언어 #C++ #IT디자이너 #C++ 함수
- C언어 #C++ #IT디자이너 #함수 #재귀 함수 #스택 #자료구조 #페인팅
- QUEUE #큐 #자료구조 #원형 큐 #Circle Queue #IT디자이너 #큐 과제 #C언어 #C++언어
- C언어 #IT디자이너 #포인터 #배열 #포인터와 배열
- C언어 #IT디자이너 #C++언어
- IT디자이너 #C언어 #C++ #속성지정자 #기억클래스 #IT #const #static #register #volatile #extern #auto #s
- C언어 #C++ #자료구조 #알고리즘 #IT디자이너 #버블 정렬 #BubbleSort
- C언어 #IT디자이너
- 디버그 #Debug #Release #디버그와 릴리즈 차이 #C언어 #C++언어 #어셈블리어
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | ||||||
2 | 3 | 4 | 5 | 6 | 7 | 8 |
9 | 10 | 11 | 12 | 13 | 14 | 15 |
16 | 17 | 18 | 19 | 20 | 21 | 22 |
23 | 24 | 25 | 26 | 27 | 28 |