[C 기초 - 비트 연산자]

Junyeong Fred Kim·2021년 12월 3일
0

C언어

목록 보기
5/21

비트 연산자


비트를 연산할 때 쓰이는 비트 연산자
비트 연산은 정수나 정수롷 변환 가능한 타입만 가능하며, 실수나 포인터 등은 비트 연산을 할 수 없다.

  • 비트는 바이트 단위보다 더 작은 단위 이며, 2진수르 저장 즉, 컴퓨터에서 사용할 수 있는 최소 단위이며 0과 1을 나타낸다.
  • 비트 연산자는 흔히 사용되는 편은 아니다. 그러나, 적절한 때에 사용하면 메모리 공간의 효율성을 높이고 연산의 수를 줄일 수 있따. 또한 비트 단위로 계산하기 때문에 일반적인 사칙연산 연산자보다 훨씬 속도가 빠르다.

연산자 종류

연산자기능
&AND 연산
lOR 연산
^XOR 연산
~모든 비트 반전, NOT 연산
<<지정한 수만큼 비트 열을 왼쪽으로 이동
>>지정한 수만큼 비트 열을 오른쪽으로 이동

& 연산자 (AND)


논리 연산자의 && 연산자와 헷갈릴 수 있는데, 논리 연산은 true와 false를 반환하고 비트 연산은 값을 반환한다.

주소값을 가리키는 & 연산자는 단항 연산자로써, 피연산자가 한개만 필요하다. 즉, &b와 같이 한개의 변수만 필요하다는 뜻. 이렇게 하나의 변수앞에서 쓰여질 때는 주소값을 나타내지만, a & b와 같이 쓰여질 때는 비트의 AND 연산자를 나타낸다.

&연산은 AND 연산인데, 두 개의 비트가 모두 1일 때 1을 반환한다. 따라서, & 연산의 결과는 다음과 같다.

AB결과값
000
010
100
111

언뜻보면 논리곱 연산과 같아보이지만, 이 연산을 비트에 사용한다는 것이 차이점이다.

이 때, 비교하는 비트는 각 수를 2진수로 변환한 후의 자리를 비교하는데, 예를 들어 10과 6이 있을 때, 10을 8비트의 2진수로 변환하면 0000 1010이 된다. 그리고 6은 0000 0110이다. 그리고 변환한 이 두 수의 같은 자리를 비교하면,(1의 자리끼리, 2의 자리끼리, 4의 자리끼리, 8의 자리끼리) 10 & 6은 0000 0010의 2가 된다.


코드

코드로 다른 예제를 보면,

#include <stdio.h>

int main()
{
	unsigned char a = 4;  // 0000 0100
	unsigned char b = 8;  // 0000 1000
	unsigned char c = a & b;
	
	printf("4와 8의 AND 연산 값 : %d\n", c);
	
	a = 6;  // 0000 0110
	b = 13; // 0000 1101
	c = a & b;
	
	printf("6과 13의 AND 연산 값 : %d", c);
	
	return 0;	
}

출력

4와 8의 AND 연산 값 : 0     // 0000 0000
6과 13의 AND 연산 값 : 4     // 0000 0100

예제 설명 전, unsigned char를 쓴 이유는 char는 8비트 변수로써 signed의 경우 -128 ~ 127까지 unsigned의 경우 0 ~ 255까지 사용이 가능하다. int의 경우 32비트 변수로 -2,147,483,648 ~ 2,147,483,647까지 사용이 가능하다. 코드에서는 비트 연산을 쉽게 이해하기 위해 작은 숫자를 이용할 것이므로, 굳이 32비트까지 써줄 필요가 없어 char를 이용.

추가로 signed의 경우 "부호 있는 정수"라 하여 맨 왼쪽 비트는 부호 비트이다. 이 부호비트를 MSB(Most Significant Bit)라 부르며 0이면 양수, 1이면 음수를 나타낸다. 따라서 MSB가 1이 되면 음수로 계산되어 보수연산을 하게 되는데, 이 보수연산이 조금 까다로우므로 부호비트에 영향을 주지 않도록 unsigned를 이용

예제 확인

첫 번째 비트 연산은 같은 자리의 비트를 비교하여 둘 다 1일 때만 1을 반환한다. 4와 8의 경우 각각 다른 자리에 1이 존재한다. 따러서 모두 0이 되며, 10진수로 표현하면 마찬가지로 0이 된다.
두번째 연산의 경우에는 4의 자리가 모두 1이며, 다른 자리는 서로 같지 않다. 따라서 4의 자리가 1로 반환되게 되며, 10진수로 표현하면 4가 된다.

| 연산자 (OR)


| 연산은 OR 연산으로, 두 개의 비트 중 하나라도 1이면 1을 반환한다.

AB결과값
000
011
101
111

코드

코드로 다른 예제를 보면,

#include <stdio.h>

int main(void)
{
	unsigned char a = 4;  // 0000 0100
	unsigned char b = 8;  // 0000 1000
	unsigned char c = a | b;
	
	printf("4와 8의 OR 연산 값 : %d\n", c);
	
	a = 6;  // 0000 0110
	b = 13; // 0000 1101
	c = a | b;
	
	printf("6과 13의 OR 연산 값 : %d", c);\
		
	return 0;	
}

출력

4와 8의 OR 연산 값 : 12
6과 13의 OR 연산 값 : 15

예제 확인

첫번째 연산의 경우 각각 4의 자리와 8의 자리에 1이 존재한다. 따라서 c는 4와 8의 자리에 1이 반환되어 10진수 값으로는 12가 된다.


두번째 연산의 경우 8,4,2,1의 자리 모두 1이 존재한다. 따라서 10진수로 15가 된다.

^ 연산자 (XOR)


^ 연산은 XOR 연산이다. 두 개의 비트가 다르면 1을, 같으면 0을 반환

AB결과값
000
011
101
110

코드

코드로 다른 예제를 보면,

#include <stdio.h>

int main(void)
{
    unsigned char a = 4;  // 0000 0100
    unsigned char b = 8;  // 0000 1000
    unsigned char c = a ^ b;
    
    printf("4와 8의 XOR 연산 값 : %d\n", c);
    
    a = 6;  // 0000 0110
    b = 13; // 0000 1101
    c = a ^ b;
    
    printf("6과 13의 XOR 연산 값 : %d", c);
    
    return 0;
}

출력

4와 8의 XOR 연산 값 : 12
6과 13의 XOR 연산 값 : 11

예제 확인

첫 번째 연산의 경우 8의 자리와 4의 자리가 서로 다르며, 나머지는 0으로 같다. 따라서 4와 8의 자리가 1이 되어 12가 된다.


두번째 연산의 경우 4의 자리만 둘 다 1로 같으며, 나머지 자리는 모두 다르다. 따라서 11이 된다.

~ 연산자 (NOT)


~ 연산은 NOT 연산자로 AND, OR, XOR과는 다르게 피연산자가 하나이다. 즉 한 값의 비트를 모두 반전 시킨다. 비트가 1이라면 0을, 0이라면 1을 반환하는 것

A결과값
01
10

코드

코드로 다른 예제를 보면,

#include <stdio.h>

int main(void)
{
	unsigned char a = 4;  // 0000 0100
	unsigned char b = 8;  // 0000 1000
	unsigned char c = ~a;
	unsigned char d = ~b;

	printf("4와 8의 NOT 연산 값 : %d, %d\n", c, d);

	a = 6;  // 0000 0110
	b = 13; // 0000 1101
	c = ~a;
	d = ~b;

	printf("6과 13의 NOT 연산 값 : %d, %d", c, d);

	return 0;	
}

출력

4와 8의 NOT 연산 값 : 251, 247
6과 13의 NOT 연산 값 : 249, 242

예제 확인

지금까지는 unsigned를 쓰지 않아도 크게 상관없는 연산들이었지만, 이 NOT연산에서는 unsigned가 활약하게 된다.
천 번째 연산의 a는 4의 자리를 제외한 나머지가 다 1로 바뀌며, 251이 된다. b는 8의 자리를 제외하고 다 1이 되므로 247이 된다.


두번째 연산의 a는 2와 4의 자리를 제외하고 1이 되며, 249가 된다. b의 경우는 1,4,8의 자리를 제외하고 1이 되므로 242가 된다.

unsigned를 사용하지 않고 부호있는 정수를 사용하면, 아래 출력과 같다.

#include <stdio.h>

int main(void)
{
	// 부호 있는 정수의 경우

	char a = 4;  // 0000 0100
	char b = 8;  // 0000 1000
	char c = ~a;
	char d = ~b;

	printf("4와 8의 NOT 연산 값 : %d, %d\n", c, d);

	a = 6;  // 0000 0110
	b = 13; // 0000 1101
	c = ~a;
	d = ~b;

	printf("6과 13의 NOT 연산 값 : %d, %d", c, d);

	return 0;
}

출력

4와 8의 NOT 연산 값 : -5, -9
6과 13의 NOT 연산 값 : -7, -14

위 코드는 음수를 출력하게 된다. MSB(부호비트)가 1로 바뀌기 때문.
MSB가 1로 바뀌면 보수연산을 하게된다.

또한, 복합 대입 연산자와 마찬가지로, 비트연산자도 대입 연산자가 존재한다.

a = a & b;
a &= b;
a = a | b;
a |= b;
profile
기억보다 기록

0개의 댓글