[C 기초 - 비트 이동 연산자]

Junyeong Fred Kim·2021년 12월 3일
0

C언어

목록 보기
6/21

비트 이동 연산자


<< 연산자 (왼쪽 Shift)

<< 연산자는 지정한 획수대로 비트의 자리를 왼쪽으로 이동시키는 연산자 입니다.

#include <stdio.h>

int main(void)
{
    unsigned char a = 4 << 1;  // 0000 0100
    unsigned char b = 8 << 2;  // 0000 1000
    
    printf("4 << 1 : %d\n", a);
    printf("8 << 2 : %d\n", b);
	
    a = 6 << 3;  // 0000 0110
    b = 10 << 4; // 0000 1010
  
    printf("6 << 3 : %d\n", a);
    printf("10 << 4 : %d\n", b);

    return 0;	
}

출력

4 << 1 : 8
8 << 2 : 32
6 << 3 : 48
10 << 4 : 160


4를 8비트 2진수로 나타낸 0000 0100을 왼쪽으로 한 자리 이동

4는 8비트 2진수로 0000 0100 입니다.

첫번째 연산에서 4가 1자리, 8이 2자리 만큼 왼쪽으로 이동한다. 왼쪽으로 이동해서 생기는 오른쪽 빈 비트들은 0으로 채워지며, 제일 왼쪽에서 밀려나는 비트들은 버려진다. 따라서 0000 0100 (4) => 0000 1000 (8)이 되고, 0000 1000 (8) => 0010 0000 (32)가 됩니다.

두번째 연산에서는 6이 3자리, 10이 4자리 만큼 왼쪽으로 이동합니다. 따라서 0000 0110 (6) => 0011 0000 (48)이 되고, 0000 1010 (10) => 1010 0000 (160)이 됩니다.

비트가 한 자리씩 왼쪽으로 이동할 때마다 정수의 값은 2배가 된다.
2진수이기 때문에 2칸을 이동하면 4배, 3칸 이동시 8배 즉, 2의 n승 만큼 곱하면 된다.

주의할 사항

  • char형의 겨우 8비트지만, int형의 경우 32비트이기 때문에 왼쪽으로 비트 이동을 할 때 잘리는 크기가 다르다.
  • 또한, unsigned 형의 경우 끝자리까지 정상적으로 이동하지만, 부호비트가 있는 자료형의 경우 MSB의 자리로 비트가 이동했을 떄에 보수연산을 하게된다.

코드

코드로 확인하기

#include <stdio.h>

int main(void)
{
	char a = 1 << 8;  // 0000 0001
	int b = 1 << 8;   // 0000 0000 0000 0000 0000 0000 0000 0001
    
	printf("(char) 1 << 8 : %d\n", a);
	printf("(int) 1 << 8 : %d\n", b);
	
	unsigned char c = 1 << 7;
	char d = 1 << 7;
	
	printf("(unsigned) 1 << 7 : %d\n", c);
	printf("(signed) 1 << 7 : %d\n", d);

}

출력

(char) 1 << 8 : 0
(int) 1 << 8 : 256
(unsigned) 1 << 7 : 128
(signed) 1 << 7 : -128

예제코드 확인

char형은 8비트기 때문에 8자리를 이동하게 되면 1이 잘려서 사라져서 0이된다.
하지만, int형은 32비트기 때문에 8자리를 이동할 수 있고, 정상적으로 256이 된다.

또한, unsigned char인 c의 경우 정상적으로 128이 되지만, 일반 char의 경우 마지막 비트가 MSB이기 때문에 음수처리되어 보수연산을 하고 그 값은 -128이 된다.

비트 이동을 할 때는 자료형을 꼭 고려할 것.


>> 연산자 (오른쪽 Shift)

>> 연산자는 지정한 획수대로 비트의 자리를 오른쪽으로 이동시키는 연산자 입니다. <<연산자와 정확히 반대이다.

#include <stdio.h>

int main(void){
	unsigned char a = 4 >> 1;  // 0000 0100
	unsigned char b = 8 >> 2;  // 0000 1000
    
	printf("4 >> 1 : %d\n", a);
	printf("8 >> 2 : %d\n", b);
	
	a = 14 >> 3;  // 0000 1110
	b = 16 >> 4; // 0001 0000
  
	printf("14 >> 3 : %d\n", a);
	printf("16 >> 4 : %d\n", b);
	
	char c = -16 >> 2;  // 1111 0000
	
	printf("-16 >> 2 : %d\n", c);
}

출력

4 >> 1 : 2
8 >> 2 : 2
14 >> 3 : 1
16 >> 4 : 1


4를 8비트 2진수로 나타낸 0000 0100을 오른쪽으로 한 자리 이동

천번째 연산에서는 4가 1자리, 8이 2자리 만큼 오른쪽으로 이동하며, 제일 오른쪽으로 밀려나는 비트들은 버려진다. 따라서 0000 0100 => 0000 0010 (2)가 되고, 0000 1000 => 0000 0010 (2)가 된다.

두번째 연산에서는 14가 3자리, 16이 4자리 만큼 오른쪽으로 이동한다. 따라서 0000 1110 => 0000 0001 (1)이 되고, 0001 0000 => 0000 0001 (1)이 된다.

여기서 알 수 있는 것은 왼쪽으로 이동할 때에는 2의 n승 만큼 곱해지지만, 오른쪽으로 이동할 떄에는 2의 n승 만큼 나누어 진다.

주의할 사항

  • 오른쪽으로 이동하면서 생기는 빈 비트들을 채워야 하는데, 양수일 때는 unsigned이든 signed이든 0이 채워져도 상관이 없다. 그러나, signed 자료형이고 음수일 때에는 맨 왼쪽값이 1이어야 하는데, 이 연산은 CPU마다 다르다. 어떤 CPU는 음수를 유지하기 위해 빈 비트들을 1로 채우고, 음수와는 상관없이 무조건 0을 채우는 CPU도 있다.

  • 일반적으로 MSB와 같은 숫자를 채우는 쪽이 많음.

  • 위 예제에서 c의 경우, 16 (1111 0000)을 2칸 오른쪽으로 이동했을 때, -4 (1111 1100)가 나오므로, MSB와 같은 1로 채워주는 것을 확인할 수 있다.

profile
기억보다 기록

0개의 댓글