본문 바로가기
Software/C++&MFC

enum의 비트연산 활용 (여러가지 조건 한번에 비교하기)

by lovey25 2018. 11. 29.
반응형

열거자라고 하는 enum의 bit 연산을 활용하면 복수의 조건을 비교선택해야 하는 상황에서 간단하게 코드를 작성할 수 있습니다. 

평소에 enum을 사용한 코드들을 보면 깊이 생각지 않고 개발자가 명명한 enum의 이름대로 직관적으로 코드의 흐름만 이해하고 넘어갔기 때문에 배우지 못했던 방법이었는데 알고나니 유용한것 같습니다.

enum의 용도

enum은 말그대로 나열되는 이름들에 차례대로 번호를 부여해서 논리적 관계를 기술하기 여려운 개념도 산술적으로 기술할수 있도록 해주는 유용한 기능입니다. 그래서 코드의 가독성이 높아지도록 할 수 있는데요. 예를 들어 다음과 같습니다.

enum day  { 	Mon=1, Tue, Wed, Thr, Fri, Sat, Sun };  
int today = Mon; 
int someday = today + 13;  
while (someday > 7) {
	someday = someday - 7; 
}  
switch (someday) { 
	case Mon: 	AfxMessageBox(_T("월요일")); 	
	break; 
	case Tue: 	AfxMessageBox(_T("화요일")); 	
    break; 
    case Wed: 	AfxMessageBox(_T("수요일")); 	
    break; 
    case Thr: 	AfxMessageBox(_T("목요일")); 	
    break; 
    case Fri: 	AfxMessageBox(_T("금요일")); 	
    break; 
    case Sat: 	AfxMessageBox(_T("토요일"));
	break; 
	case Sun: 	AfxMessageBox(_T("일요일")); 
} 

만약 오늘이 날짜로는 1일이고 요일로는 월요일이라면, 13일후에는 무슨날일까요를 알려주는 코드죠?! 날짜는 1 + 13 하면 쉽게 14일인걸 알수 있습니다. 단순한 덧셈이죠 그런데 요일은 어떨까요?

컴퓨터는 월요일 더하기 하루는 화요일이라는 개념이 전혀 없겠죠. "월요일"이 뭔지도 이해 못하겠죠.

그래서 enum으로 월요일은 숫자 1로 지정하고 차례대로 화요일부터 일요일까지 나열을 하게되면 알아서 Mon=1  부터 Sun=7까지를 지정해 줍니다. 지정이 끝났으니 이제 우리는 코딩을 할때 아무런 생각없이 월요일은 Mon으로 써주고 화요일은 Tue라고 직관적으로 써주기만 하면 됩니다. 

이런 이름 지정이 없는 경우에는 어떨까요? 월요일인 경우 Mon 대신 숫자 1을 코드에 사용하게 되면 소스가 길어지거나 나중에 다시 확인할때 숫자 1이 일요일이었던가 월요일이었던가 혼란스러울 수 있겠죠. 그럼 다시 정의를 찾아봐야 하는데 Mon이라고 해 놓으면 누가봐도 월요일인걸 알수 있겠네요.

enum의 bit연산

이제 enum의 bit 연산에 대해서 알아보겠습니다.

앞의 코드를 이렇게 바꿔봤습니다.

enum day  {
	Mon = 0b00000001, // 1 	
	Tue = 0b00000010, // 2 	
	Wed = 0b00000100, // 4 	
	Thr = 0b00001000, // 8 	
	Fri = 0b00010000, // 16 	
	Sat = 0b00100000, // 32 	
	Sun = 0b01000000  // 64 
};  
int i_like = 0b00000011; 
int you_like = 0b01000001;  
switch (i_like & you_like) { 
    case Mon: 	AfxMessageBox(_T("월요일")); 	
    break; 
    case Tue: 	AfxMessageBox(_T("화요일")); 	
    break; 
    case Wed: 	AfxMessageBox(_T("수요일")); 	
    break; 
    case Thr: 	AfxMessageBox(_T("목요일")); 	
    break; 
    case Fri: 	AfxMessageBox(_T("금요일")); 	
    break; 
    case Sat: 	AfxMessageBox(_T("토요일")); 	
    break; 
    case Sun: 	AfxMessageBox(_T("일요일")); 
    default: 	AfxMessageBox(_T("없어없어~")); 
} 

월요일부터 일요일까지 차례대로 Mon에는 1, Tue에는 2, Wed에는 4 ... Sun에는 64를 지정하였습니다. 한마디로 첫번째 비트는 월요일 두번째 비트는 화요일 ... 일곱번째 비트는 일요일로 지정을 하겠다는 거죠. 그리고 각 비트를 바로 확인할 수 있도록 2진수로 입력하였습니다. 

그리고 변수를 2개 선언했는데요 하나는 내가 좋아하는 요일을 담을 변수 "i_like"와 네가 좋아하는 요일을 담을 변수 "you_like" 입니다. 

내가 좋아하는 요일은 첫번째와 두번째 비트만 1로 했으니 월요일과 화요일이 되겠고,

네가 좋아하는 요일은 첫번째와 일곱번째 비트만 1이니 월요일과 일요일 이겠죠.

그리고 switch 문에서 "&"연산을 하는데, 내가 좋아하는 요일과 네가 좋아하는 요일을 &연산 했으니 결과는 나랑 너랑 서로 같이 좋아하는 요일이 되겠죠?! 바로 월요일입니다. (예제를 특이하게 했네요 ㅋ)

이런식으로 enum으로 비트마스크를 만들어서 특정 조건을 확인하는 용도로도 사용할 수 있다고 합니다.

enum의 bit연산 - 약간 다른 활용

위의 bit연산을 약간 다른방법으로도 이용할 수 있는데 그 방법도 같이 적어놓겠습니다.
급조된 예제라 뭔가 이상해 보이지만 그냥 활용을 설명하기 위함이니 그러려니 해주세요.
enum Lan { 	
    Kor = 0b00000001, // 1 	
    Eng = 0b00000010, // 2 	
    Jpn = 0b00000100, // 4 	
    Chi = 0b00001000, // 8 
};  
int i_speak = 0b00100001; // Kor 
Lan lan = (Lan)0b00001111;  
if ((lan & i_speak)) { 	
    AfxMessageBox(_T("통과")); 
} 
else {
    AfxMessageBox(_T("탈락")); 
} 

어떤 회사에서 사람을 채용하는데 한국어, 영어, 일본어, 중국어 4개중 하나라도 할 수 있는 사람을 뽑기위한 필터링을 한다고 생각해보죠.

enum으로 아래 4개의 비트를 각각 Kor, Eng, Jpn, Chi로 지정하고 "Lan"이라는 열거자로 정의가 되었습니다. 그리고 이 열거자를 "lan"이라는 이름으로 선언을 해 주었습니다. 앞에서 예제와 다른 부분이죠.

바로 이 부분이 특정 조건을 필터링할 마스크가 되는 겁니다. 4개의 언어 모두 가능한 지원자를 찾아야 하기 때문에 초기값을 "0b00001111"로 설정하였습니다.

그리고 지원자의 능력을 "i_speak"이라는 변수에 담았다고 해보죠. 이 지원자는 1번째 비트에 해당하는 한국어(Kor)이 가능하다고 표시되어 있고 6번째 비트에 뭔지 모르는 또하나의 언어가 가능한것으로 보이는 군요. 그러면 통과죠. 마스크로 사용할 "lan"과 "i_speak"을 bit 연산해서 원하는 결과를 얻을 수 있습니다.

실제로는 좀더 스마트하게 사용할 수 있는 구문인데 예제가 허접해서 나중에 다시보면 이게 뭐야 할 수도 있겠지만 이렇게도 사용할 수 있구나를 위해 남겨둡니다. ㅎ

 

끝!

반응형

댓글