비트 연산자는 비트 단위로 연산을 진행하는 것으로 주로 하드웨어 프로그래밍에 활용되고, 그 이외의 영역에서는 메모리 공간의 효율성을 높이고 연산의 수를 줄이는 데 사용된다.

연산자 연산자의 기능
& 비트 단위로 AND 연산을 한다.
num1 & num2;
| 비트 단위로 OR 연산을 한다.
num1 | num2;
^ 비트 단위로 XOR 연산을 한다.
num1 ^ num2;
~ 단항 연산자로서 피연산자의 모든 비트를 반전시킨다.
~num; // num은 변화 없고 반전 결과만 반환
<< 피연산자의 비트 열을 왼쪽으로 이동시킨다
num<<2; // num은 변화 없고 두 칸 왼 쪽 이동 결과만 반환
>> 피연산자의 비트 열을 오른쪽으로 이동시킨다.
num>>2; // num은 변화 없고 두 칸 오른쪽 이동 결과만 반환

 

&연산 : AND

&연산은 두 개의 비트가 모두 1일때 1을 반환하고, 아니면 0을 반환한다.

ex) 0 & 0 -> 0 / 1 & 0 -> 0 / 0 & 1 -> 0 / 1 & 1 ->0

#include <stdio.h>

int main(void){
  int num1 = 15;  // 00000000 00000000 00000000 00001111
  int num2 = 20;  // 00000000 00000000 00000000 00010100
  int num3 = num1 & num2; // 00000100 = 4

  printf("num1 AND num2 result : %d\n", num3);
  return 0;
}
// output : num1 AND num2 result : 4

 

|연산 : OR

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

ex) 0 | 0 -> 0 / 1 | 0 -> 1 / 0 | 1 -> 1 / 1 | 1 -> 1

#include <stdio.h>

int main(void){
  int num1 = 15;  // 00000000 00000000 00000000 00001111
  int num2 = 20;  // 00000000 00000000 00000000 00010100
  int num3 = num1 | num2; // 00011111 = 31

  printf("num1 OR num2 result : %d\n", num3);
  return 0;
}
// output : num1 OR num2 result : 31

 

^연산 : XOR

^ 연산은 두 개의 비트가 서로 다른 경우에 1을 반환한다.

ex) 0 ^ 0 -> 0 / 1 ^ 0 -> 1 / 0 ^ 1 -> 1 / 1 ^ 1 -> 0

#include <stdio.h>

int main(void){
  int num1 = 15;  // 00000000 00000000 00000000 00001111
  int num2 = 20;  // 00000000 00000000 00000000 00010100
  int num3 = num1 ^ num2; // 00011011 = 27

  printf("num1 XOR num2 result : %d\n", num3);
  return 0;
}
// output : num1 XOR num2 result : 27

 

~연산 : NOT

~연산은 비트를 0에서 1로, 1에서 0으로 반전시킨다. 보수 연산이라고도 불린다.

~0 -> 1 / ~1 -> 0

#include <stdio.h>

int main(void){
  int num1 = 15;  // 00000000 00000000 00000000 00001111
  int num2 = ~num1;

  printf("NOT num1 result : %d\n", num2);
  return 0;
}
// output : NOT num1 result : -16

NOT 연산은 비트의 부호를 결정하는 MSB도 반전되어 값이 음수로 반전되었다.

 

<<연산 : 비트 왼쪽 이동(Shift)

<< 연산은 두 개의 피연산자를 요구하고 왼쪽 피연산자의 비트열을 오른쪽 피연산자의 값만큼 왼쪽으로 이동한다는 의미를 갖는다.

#include <stdio.h>

int main(void){
  int num = 15; // 00000000 00000000 00000000 00001111

  int res1 = num << 1;
  // 00011110
  int res2 = num << 2;
  // 00111100
  int res3 = num << 3;
  // 01111000

  printf("1 left shift : %d\n", res1);
  printf("2 left shift : %d\n", res2);
  printf("3 left shift : %d\n", res3);
  return 0;
}
/*
output :
1 left shift : 30
2 left shift : 60
3 left shift : 120
*/

위 코드를 보면 비트의 열을 한 칸씩 왼쪽으로 이동시킬때 마다 정수의 값이 두배가 되고, 반대로 한 칸씩 오른쪽으로 이동시키면 1/2배가 된다는 것을 알 수 있다. 이를 잘 활용하면 프로그램의 성능 향상으로도 이어질 수 있다. 

 

>>연산 : 비트 오른쪽 이동(shift)

>> 연산은 오른쪽 피연산자의 크기만큼 왼쪽 피연산자의 비트열이 오른쪽으로 이동한 결과가 나타난다. 왼쪽 피연산자의 값이 양수라면 밀려나는 오른쪽 비트들은 소멸되고 이동으로 인해 생긴 왼쪽 빈자리는 0으로 채워진다. 그러나 왼쪽 피연산자 값이 만약 음수라면 CPU에 따라 음의 값을 유지하기 위해 1을 채우는 CPU도 있고, 음의 값 유지를 상관하지 않고 0을 채우는 CPU도 있다. 

#include <stdio.h>

int main(void){
  int num = -16;  // 11111111 11111111 11111111 11110000
  printf("2 right shift : %d\n", num>>2);
  printf("3 right shift : %d\n", num>>3);
  return 0;
}
/*
output:
2 right shift : -4
3 right shift : -2
*/

 

위의 경우는 CPU에서 음의 값 유지를 위해 1을 채운 경우이다.

'Language > C, C++' 카테고리의 다른 글

[C] unsigned  (0) 2020.11.25
[C] 자료형  (0) 2020.11.25
[C] 진수 표현  (0) 2020.11.21
[C] 키워드  (0) 2020.11.21
[C] scanf()  (0) 2020.11.21

+ Recent posts