C++ - 조건식(if, switch,삼항연산자), 비트연산자

이강민·2023년 8월 19일

C++

목록 보기
4/22
post-thumbnail

조건식

비교연산자

== : 같을 경우
!= : 같지 않을 경우
<, >, <=, >= : 크기를 비교

위와 같은 비교 연산자를 이용하여 조건식을 만든다.

if문

if(조건식) {
	실행 문
}

if(조건식){
	실행
} else if(조건식) {
	실행
}

if(조건식){
	실행
}else{
	실행
}

if문은 위와 같이 3가지 방식으로 사용할 수 있다.
else if나 else를 사용 시 상단의 문장이 조건을 만족하였을 때 하위의 조건은 실행하지 않는다.

if (100 && 200) {
	//전체 연산결과 true 1
	data = 200;
	cout << data << endl;
};

if (data == 100) {
	data = 200;
	cout << data << endl;
}else if(data == 200){
cout << "데이타" << endl;
}
else if (100) {
	cout << "실행"  << endl;
}

switch문

switch 문을 사용할 때 주의 사항으로 각 조건마다 걸려있는 break를 사용하지 않으면 이하 모든 조건을 모두 실행한다. 의도하지 않는다면 break 작성을 해야한다.

	int iTest = 20;
	switch (iTest) {
	case 10 : 

		cout << "테스트가 아냐" << endl;
		break;
	case 20:
		cout << iTest << endl;
		break;
	case 30:
		cout << "break 안씀" << endl;
		break;
	default: break;

	}

삼항연산자

삼항 연산자를 이용하여 코드를 좀 더 간결하게 만들 수 있으나 남용하게 되면 가독성이 떨어지니 단순한 조건식을 간결하게 표현할때 적절하다.
다음과 같은 조건식을 삼항연산자로 만들 수 있다.

if문

	if (iTest == 20) {
		iTest = 10;
	}
	else {
		iTest = 30;
	};

삼항연산자

	iTest == 20 ? iTest = 10 : iTest = 30;

비트연산자

쉬프트 연산자

비트를 좌 또는 우측으로 미는 연산자이다.

unsigned char test = 1; 
//좌로 3만큼 이동시키서 값을 할당한다.
test <<= 3
// 위의 연산자는 다음과 같다. tset = test << 3;

좌 쉬프트 연산자를 사용하여 비트를 이동시키면 다음과 같다.

우 쉬프트 연산자를 사용하여 비트를 이동시키면 다음과 같다.

만약 13과 같은 2로 나누어 떨어지지 않는 수는 어떻게 처리할까?

즉, 2^n으로 나눈 몫이 우 쉬프트의 결과라고 할 수 있다.

//쉬프트 연산자 << , >> 
unsigned char byte = 2;
byte <<= 3; //2^n으로 곱한 수 , 2 x 8 = 16
byte = 8;
byte >>= 3; // 2^n으로 나눈 몫 8 / 8 = 1로 몫은 1이된다.  
byte = 13;
byte >>= 2; //2^n으로 나눈 몫 13 / 4  = 3.25로 몫은 3이된다.

비트 곱 &, 합 | , XOR ^, 반전 ~

비트 단위로 연산을 수행하는 연산자로
비트 곱은 &
비트 합은 |
XOR은 ^
비트 반전은 ~을 사용한다.

비트 곱 &

비트 곱은 두개 의 연산 대상 중 둘다 1인 경우에 1이된다.

즉, 13&3의 비트 연산 결과는 1이 된다.

unsigned char result = 13 & 3;
cout << "연산결과 : " << (13 & 3) << endl; // 연산결과 : 1

비트 합 |

비트 합은 두개의 연산 대상 중 하나의 비트가 1이 되면 1이 된다.

unsigned char result = 13 | 3;
cout << "연산결과 : " << (13 | 3) << endl; // 연산결과 : 15

XOR ^

각각의 비트가 같으면 0, 다르면 1이된다.

unsigned char result = 13 ^ 3;
cout << "연산결과 : " << (13 ^ 3) << endl; // 연산결과 : 14

반전 ~

비트가 0이면 1, 1이면 0이 된다.

	unsigned char test = ~251;
	printf("연산결과 %d\n", test);

비트 연산을 사용하는 이유

어떤 단순한 상태를 비트단위로 저장하고 싶을 때 사용한다.
예를 들어 시뮬레이터 게임을 개발한다고 가정해보자

게임은 정교하게 사람을 모방하는 캐릭터를 만들어서 허기짐, 불쾌함, 목마름, 더움 등의 상태를 가진다고 가정해본다.

만약 비트단위로 저장한다면 어떻게 할 수 있을까?

위 그림처럼 각각의 상태를 비트단위로 표현해 볼 수 있다.

뿐만 아니라 게임 옵션의 부분을 비트단위로 저장할 수 있다.
아래 예시는 캐릭터의 상태를 저장해보는 예이다.

#include <iostream>
using namespace std;
// 보통 비트로 상태를 표현한다면 16진수로 표현한다.
#define HUNGRY	0x001
#define THIRSTY 0x002 
#define TIRED	0x004
#define HOT		0x008

#define POISION 0x010
#define SWEET	0x020
#define TIRTY	0x040
#define CLEAN	0x080

int main() {
 
	//정상적인 상태 모든 비트가 0일 경우
	int iState = 0;
	//배가 고파질 경우, 비트합으로 상태를 축적
	iState |= HUNGRY;
	// 목도 말라지는 것
	iState |= THIRSTY;
return 0;

}

#define
전처리 define 사용하는 이유 ?
고유의 값을 저장할 필요가 있으면 전처리 define 기능을 사용하는 것이 좋다.
define으로 설정해두면 값이 변경될 때 한번만 바꾸면 된다.
즉, 가독성과 유지보수 차원에서 좋다.

위 코드에서 전처리 define 들의 비트는 다음과 같다.

배고픈 상태를 추가한다면 비트 합을 이용하여 상태를 추가할 수 있다.

목이 마른 상태까지 추가하였으니 다음과 같이 비트를 형성한다.

해당 상태를 검사하고 싶으면 비트곱을 이용하여 확인 할 수 있다.

//만약 배가 고픈경우, 현재 배가 고픈 비트가 1, 목이 마른 비트가 1이다. 
// HJNGRY의 비트가 1이니 &로 비교하면 참이 나온다.
if (iState & HUNGRY) {
	cout << "배고파요" << endl; 
}

캐릭터가 음식을 먹어 배고픔이 해소가 되었다고 가정해보자
그렇다면 특정 비트만 제외시킬 수 있어야 한다.

XOR을 이용해보자

iState = istate ^ HUNGRY;

특정 비트를 제거한 것처럼 보이지만 여기에는 하나의 문제점이 있다.
만약 배고픈 상태가 아닌데 배고픔을 해제한다면 어떻게 될까?

XOR 연산에 의해서 배고픈 상태가 아닌데 배고픈 상태로 바뀌게 되었다.

다른 방법을 이용해보자

iState = iState & (~HUNGRY);

검사하고자하는 비트를 반전 시킨 다음 비트 곱을 이용하여 비트를 연산하면 특정 비트를 제거 할 수 있다.

위 그림과 같이 비트를 반전시키고

iState 값과 비트 곱 연산을 해주면 특정 비트를 제거 할 수 있다.
만약 배고픈 상태가 아니더라도 상관없다.

배고픈 상태가 아니면 변하지 않는다.

iState &= ~HUNGRY;

위 비트 연산은 특정 비트를 제거할 때 많이 사용하니 외워두면 유용하다.

profile
AllTimeDevelop

0개의 댓글