티스토리 뷰

안녕하세요, 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디자이너였습니다.

 

감사합니다. 

공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
TAG more
«   2024/10   »
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 29 30 31
글 보관함