프로그래밍 언어/C C++

c언어의 비트 연산 및 비트 연산자

트리맨스 2019. 4. 30. 00:24
반응형

C언어의 비트 연산을 배우고 나서 좀 헷갈려서 정리하려 합니다.

비트 연산이란, 변수 안에 있는 수를 2진수로 변환 후 각 자릿수에 대해 연산자를 이용해 연산하는 것이다.

비트 연산자에는 & (and) , | (or) , ^ (xor) , ~(not) ,<<,>>(왼쪽,오른쪽으로 비트 이동)이 있다.

 

and는 둘다 1일때 1출력

or는 하나라도 1일때 1출력

xor는 or에서 둘다 1일때 0을 출력

not은 1이면 0출력 0이면 1출력 한다.

 

그럼 이제 응용해보자.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
#include <stdio.h>
 
int main()
{
    char a=4,b=15,c=127,d,e,j=22;
    unsigned char f,g,h;
    unsigned char i=0xbf;
    
    printf("%d %d %d\n",a,b,c);
    printf("%d %d %d\n",a<<1,a>>2,a>>3);
    printf("%d %d %d %d\n",c<<1,c<<2,d=c<<2,f=c<<2);
    
    printf("%d %d %d\n",sizeof(c),sizeof(c<<1),sizeof(c<<2));
    
    printf("%d %d %d %d\n",a&j,a|j,a^j,~a);
    
    printf("%x %x %x",b&(i>>4),b&i,i);
      
    return 0;
}
cs

 

실행결과

4  15  127
8  1  0
254  508  -4  252
1  4  4
4  22  18  -5
b  f  bf

 

 

첫째줄은 당연히 4, 15, 127이 출력된다.

 

두번째 줄을 보자. 두번째 줄의 출력결과는 8, 1, 0 이다.

각 수를 2진수로 변환해서 생각해보자.

4를 이진수로 변환하면 0000 0100

15를 이진수로 변환하면 0000 1111

127을 이진수로 변환하면 0111 1111 이다.

0000 0100 을 왼쪽으로 1비트씩 움직이면(<<1) 0000 1000 이 된다.

이 때 제일 왼쪽 0에서는 끌어올게 없기 때문에 0을 끌어온다. 그러므로 0000 1000 이 나온다. 

마찬가지로 (>>2)를 실행하면 0000 0001이 되기 때문에 1이 출력된다.

그렇다면 여기서 한번더 오른쪽으로 가면 어떻게될까? 답은 0000 0000이다. 제일 왼쪽에 있던 1은 사라진다.

 

세번째 줄을 보자. 세번째 줄의 실행 결과는 254, 508, -4, 252 가 나온다.

c는 0111 1111이다. 이것을 왼쪽으로 1칸 옮기면 1111 1111이 되므로 -1이 아닐까? 하지만 254가 나온다.

c 변수 그 자체는 char 형태로 존재할 수 없는 것이다. 네번째 줄 두번째 수는 c<<1 의 크기가 4바이트라고 알려준다.

마찬가지로 c<<2를 실행하면 508이 나온다. 자료형 자체가 바뀌었기 때문이다. 

그렇다면 세번째줄 세번째 수는 왜 -4가 나올까? 간단하다. signed char 자료형에 비트를 가져다 박았기(?) 때문이다.

c<<2 를 char 형태 안에서 표현하면 1111 1100 이 나온다. 이것은 -4를 나타낸다.

하지만 세번째줄 네번째 수는 252를 가르킨다. 왜냐하면, unsigned char 자료형에 비트를 붙여넣었기 때문이다.

맨 앞자리 비트가 부호비트가 아니라 일반 숫자비트 이므로 252가 나온다.

 

네번째 줄은 각 자료형의 크기를 나타낸 것이다. 

char는 1바이트, c<<1 과 c<<2 는 4바이트로 늘어난 모습이다. 

 

다섯번째 줄에선 a랑 j의 연산이다. 출력은 4, 22, 18, -5 가 나온다.

a는 0000 0100 이고 j는 0001 0110 이다. 

각 자리의 계산은 녹색 네모를 보자. 녹색 네모에서의 계산 결과가 아래에 적힌다.

AND 계산
OR 계산
XOR 계산.

즉, 순서대로 4, 22, 18 이 출력된다. NOT 계산은 각 비트를 반전시켜주면 된다.

NOT 계산의 예) 0110 -> 1001

 

마지막으로 이것을 응용해 16진수의 각 자릿수를 분리하는 것을 볼 수 있다.

16진수  bf는 2진수로 1011 1111 이다. 10진수 15는 2진수로 0000 1111 이다.

AND 연산자를 쓰면 0은 버려지고 1만 살리므로 각 자릿수를 분리할 수 있다.

f(15)를 분리한 모습이다.
b(11)을 분리한 모습이다.

그렇게 출력은 f,b 가 나온다. 마지막으로 원본이랑 대조하기 위해서 i를 출력시켰다.

 

반응형