평소 잘 이해가 안됐던 bitwise 연산자에 대해 정리해보도록 하겠다.
shift 연산자
>>
<<
AND, OR, XOR 연산자
&
|
^
NOT 연산자 (Unary operator)
~
※ Bitwise 연산자는 정수 타입에서만 사용할 수 있다.
<<
- 자릿수를 왼쪽으로 옮기는 기능을 한다. (넘어가는 자리 수는 무시)
- i << j는 i를 이진법으로 표현했을 때 자릿수를 j만큼 왼쪽으로 옮긴다. (원래 i의 왼쪽 j개 비트는 없어진다.)
- 부호가 변하지 않는 한 2^j배 한 효과가 있다.
i = 2017;
j = i << 2; //j = 8068
i = 00000000 00000000 00000111 11100001
j = 00000000 00000000 00011111 10000100
2^2 = 4, i의 4배한 값이 j가 된다.
>>
- 자릿수를 오른쪽으로 옮기는 기능
- 왼쪽은 sign bit로 채워진다. (양수이면 0, 음수이면 1이 채워짐)
- 2^j로 나눈 효과
i = 2017;
j = i >> 2; // j=504
2017/4 = 504
비트연산자는 다른 산술 연산자보다 우선순위가 낮다.
*나 /연산자보다 연산 속도가 좋다.
&, |, ^, ~
a & b // 이진수 표현에서 각 자리가 둘 다 1이면 1
a | b // 자리가 둘 다 0이면 0
a ^ b // 자리가 같으면 0, 다르면 1
~a // 0과 1을 서로 바꾼 값
연산결과
연산자 | 비트1 | 비트2 | 결과 |
& | 0 | 0 | 0 |
0 | 1 | 0 | |
1 | 0 | 0 | |
1 | 1 | 1 | |
| | 0 | 0 | 0 |
0 | 1 | 1 | |
1 | 0 | 1 | |
1 | 1 | 1 | |
^ | 0 | 0 | 0 |
0 | 1 | 1 | |
1 | 0 | 1 | |
1 | 1 | 0 |
코딩도장 c코드를 첨부한다.
#include <stdio.h>
int main()
{
unsigned char num1 = 1; // 0000 0001
unsigned char num2 = 3; // 0000 0011
printf("%d\n", num1 & num2); // 0000 0001: 01과 11을 비트 AND하면 01이 됨
printf("%d\n", num1 | num2); // 0000 0011: 01과 11을 비트 OR하면 11이 됨
printf("%d\n", num1 ^ num2); // 0000 0010: 01과 11을 비트 XOR하면 10이 됨
return 0;
}
복합 연산자
+=, -=처럼 사용가능하다.
<<=, >>=, &=, |=, ^=
활용법
이진법 구성을 바꾸거나 확인
- 각 자리 정하기
- 각 자리에 저장된 값 확인하기
두 개의 변숫값 서로 바꾸기
2의 거듭제곱으로 나눈 나머지 판별
각 자리 정하기
- 1로 정할 때는 |=, 0으로 정할 때는 &=연산자를 사용
1) i = 2017 (11111100001)에서 오른쪽에서 3번째 비트만 1로 바꾸고 싶을 때
i |= 4; 또는 i |= 0x4; //i=2021(11111100101)
2) i의 오른쪽에서 8번째 비트만 0으로 바꾸고 싶을 때
i &= 0xFFFFFF7F; 또는 i &=~0x80; //i=1893(11101100101)
3) i의 오른쪽에서 j번째 비트만을 1또는 0으로 바꾸기
i |= (1 << (j-1)); //1으로 바꿈
i &= ~(1 << (j-1)); //0으로 바꿈
4) i의 오른쪽에서 연속 j개 bit만을 1로 정하기
i |= ((1 << j) - 1); 또는 i |= ~(-1 << j);
5) i의 오른쪽에서 연속 j개 bit만을 0으로 정하기
i &= ~((1 << j) - 1); 또는 i &= (-1 << j);
6) i의 왼쪽에서 연속 j개 bit만을 1로 정하기 (char형이면 32대신 8을 씀)
i |= (-1 << (32 - j));
7) i의 왼쪽에서 연속 j개 bit만을 0으로 정하기 (char형이면 32대신 8을 씀)
i &= ~(-1 << (32 - j));
각 자릿수 확인하기
1) i의 오른쪽에서 j번째 비트를 확인
i & (1 << (j-1))
1이면 위의 값이 0이 아니고, 0이면 0이다.
2) i의 연속된 j개의 비트 확인
오른쪽 j개 비트
i & ~(-1 << j) 또는 i & ((1 << j) - 1)
왼쪽 j개 비트 (char형이면 8)
i & (-1 << (32 - j))
3) 2의 거듭제곱으로 나눈 나머지 판별
if(i & 1){
// case for odd number
}
else{
// case for even number
}
switch(i & 3){
case 0:
// case for i = 4k
case 1:
// case for i = 4k + 1
case 2:
// case for i = 4k + 2
case 3:
// case for i = 4k + 3
}
a와 b의 값 바꾸기
a ^= b;
b ^= a;
a ^= b;
XOR을 이용해 두 변숫값을 바꿀 수 있다.
이건 유용하게 쓰일 것 같다.
'C' 카테고리의 다른 글
[C] 표준 입력 함수 scanf, getchar, gets, getch, getche, fgets) (0) | 2021.05.23 |
---|---|
[C] 이중 포인터 (0) | 2021.05.02 |
[C 기초] return문 (0) | 2021.03.27 |
[C 기초] 변수명 사용 규칙, 예약어 (0) | 2021.03.23 |
[C 기초] 이스케이프 시퀀스 (0) | 2021.03.23 |