비트 연산 기본에 대해서 알아보자. (get, set, clear, toggle, check)
- 비트 1개 연산
- 연속된 여러 비트 연산
- 비트 마스크 연산
비트 1개 연산
다음의 코드를 실행시켜보자.
#include <stdio.h>
typedef long long int ll;
#define SET_BIT(value, n) ((value) |= (1ull << (n)))
#define CLEAR_BIT(value, n) ((value) &= ~(1ull << (n)))
#define TOGGLE_BIT(value, n) ((value) ^= (1ull << (n)))
#define CHECK_BIT(value, n) (((value) & (1ull << (n))))
#define CHECK_BIT_BOOL(value, n) (!!((value) & (1ull << (n))))
template <typename T>
void printBitNumber(T number)
{
unsigned int bitSize = sizeof(number) * 8;
T mask = (1ull) << (bitSize - 1);
printf("%d", (number & mask) == mask);
mask = (1ull) << (bitSize - 2);
for (int i = 1; i < bitSize; i++)
{
printf("%d", (number & mask) == mask);
mask >>= 1;
if (i % 8 == 7) printf(" ");
}
putchar('\n');
}
int main(void)
{
ll number = 0x1234123412341234;
printBitNumber(number);
SET_BIT(number, 63);
SET_BIT(number, 62);
SET_BIT(number, 61);
SET_BIT(number, 60);
CLEAR_BIT(number, 59);
CLEAR_BIT(number, 58);
CLEAR_BIT(number, 57);
CLEAR_BIT(number, 56);
TOGGLE_BIT(number, 55);
TOGGLE_BIT(number, 54);
TOGGLE_BIT(number, 53);
TOGGLE_BIT(number, 52);
printBitNumber(number);
printf("%lld\n", CHECK_BIT(number, 51));
printf("%lld\n", CHECK_BIT(number, 50));
printf("%lld\n", CHECK_BIT(number, 49));
printf("%lld\n", CHECK_BIT(number, 48));
printf("%d", CHECK_BIT_BOOL(number, 51));
printf("%d", CHECK_BIT_BOOL(number, 50));
printf("%d", CHECK_BIT_BOOL(number, 49));
printf("%d", CHECK_BIT_BOOL(number, 48));
return 0;
}
SET_BIT로 63 - 60번째를 모두 1로 변경하였다.
CLEAR_BIT로 59 - 56번째를 모두 0으로 변경하였다.
TOGGLE_BIT로 55 - 52번째 값을 토글시켰다.
CHECK_BIT로 51 - 48번째 값이 0인지 1인지 확인할 수 있다.
CHECK_BIT는 if문에서 주로 사용할 수 있다.
비트의 값이 0인지 1인지 얻기 위해서 CHECK_BIT_BOOL에 !! 연산을 추가해 0은 0으로 그 외 값은 1로 만들었다.
CHECK_BIT_BOOL은 결국 GET_BIT로 볼 수 있다.
따라서 아래와 같이 다시 정의가 가능하다.
#define CHECK_BIT_BOOL(value, n) (!!((value) & (1ull << (n))))
#define GET_BIT(value, n) (CHECK_BIT_BOOL(value, n))
또는 아래와 같이 정리할 수 있다.
#define GET_BIT(value, n) (!!((value) & (1ull << (n))))
#define SET_BIT(value, n) ((value) |= (1ull << (n)))
#define CLEAR_BIT(value, n) ((value) &= ~(1ull << (n)))
#define TOGGLE_BIT(value, n) ((value) ^= (1ull << (n)))
#define CHECK_BIT(value, n) (((value) & (1ull << (n))))
연속된 여러 비트 연산
위의 내용을 확장하면 여러 개의 비트도 처리가 가능하다.
주로 mask가 연속된 1비트인 경우에 자주 사용한다. (value의 n번째 여러 비트를 처리)
#define GET_BIT(value, n) (!!((value) & (1ull << (n))))
#define GET_BITS(value, mask, n) (((value) >> (n)) & (mask))
#define SET_BIT(value, n) ((value) |= (1ull << (n)))
#define SET_BITS(value, mask, n) ((value) |= ((mask) << (n)))
#define CLEAR_BIT(value, n) ((value) &= ~(1ull << (n)))
#define CLEAR_BITS(value, mask, n) ((value) &= ~((mask) << (n)))
#define TOGGLE_BIT(value, n) ((value) ^= (1ull << (n)))
#define TOGGLE_BITS(value, mask, n) ((value) ^= ((mask) << (n)))
#define CHECK_BIT(value, n) (((value) & (1ull << (n))))
아래의 코드를 실행해보자.
#include <stdio.h>
typedef long long int ll;
#define GET_BIT(value, n) (!!((value) & (1ull << (n))))
#define GET_BITS(value, mask, n) (((value) >> (n)) & (mask))
#define SET_BIT(value, n) ((value) |= (1ull << (n)))
#define SET_BITS(value, mask, n) ((value) |= ((mask) << (n)))
#define CLEAR_BIT(value, n) ((value) &= ~(1ull << (n)))
#define CLEAR_BITS(value, mask, n) ((value) &= ~((mask) << (n)))
#define TOGGLE_BIT(value, n) ((value) ^= (1ull << (n)))
#define TOGGLE_BITS(value, mask, n) ((value) ^= ((mask) << (n)))
#define CHECK_BIT(value, n) (((value) & (1ull << (n))))
template <typename T>
void printBitNumber(T number)
{
unsigned int bitSize = sizeof(number) * 8;
T mask = (1ull) << (bitSize - 1);
printf("%d", (number & mask) == mask);
mask = (1ull) << (bitSize - 2);
for (int i = 1; i < bitSize; i++)
{
printf("%d", (number & mask) == mask);
mask >>= 1;
if (i % 8 == 7) printf(" ");
}
putchar('\n');
}
int main(void)
{
ll number = 0x1234123412341234;
printBitNumber(number);
ll mask = 0x00000000000000FF;
printBitNumber(mask);
SET_BITS(number, mask, 2);
printBitNumber(number);
return 0;
}
number에서 2번째 bit부터 FF = 1111 1111이 set 되도록 SET_BITS가 처리하였다.
비트 마스크 연산
마찬가지로 임의의 mask를 이용해서 mask에 입력된 값만 set, clear, toggle할 수 있다.
#include <stdio.h>
typedef long long int ll;
#define SET_BITMASK(value, mask) ((value) |= (mask))
#define CLEAR_BITMASK(value, mask) ((value) &= (~(mask)))
#define TOGGLE_BITMASK(value, mask) ((value) ^= (mask))
template <typename T>
void printBitNumber(T number)
{
unsigned int bitSize = sizeof(number) * 8;
T mask = (1ull) << (bitSize - 1);
printf("%d", (number & mask) == mask);
mask = (1ull) << (bitSize - 2);
for (int i = 1; i < bitSize; i++)
{
printf("%d", (number & mask) == mask);
mask >>= 1;
if (i % 8 == 7) printf(" ");
}
putchar('\n');
}
int main(void)
{
ll number;
ll mask = 0xFF00000000001200;
printf("mask : "); printBitNumber(mask);
putchar('\n');
number = 0x1234123412341234;
printf("before : "); printBitNumber(number);
SET_BITMASK(number, mask);
printf("after : "); printBitNumber(number);
putchar('\n');
number = 0x1234123412341234;
printf("before : "); printBitNumber(number);
CLEAR_BITMASK(number, mask);
printf("after : "); printBitNumber(number);
putchar('\n');
number = 0x1234123412341234;
printf("before : "); printBitNumber(number);
TOGGLE_BITMASK(number, mask);
printf("after : "); printBitNumber(number);
putchar('\n');
return 0;
}
코드를 실행하면 mask에 1이 적힌 부분만 1로 set / 0으로 clear / toggle 되는 것을 알 수 있다.
전체 코드는 다음과 같다.
#include <stdio.h>
typedef long long int ll;
#define GET_BIT(value, n) (!!((value) & (1ull << (n))))
#define GET_BITS(value, mask, n) (((value) >> (n)) & (mask))
#define SET_BIT(value, n) ((value) |= (1ull << (n)))
#define SET_BITS(value, mask, n) ((value) |= ((mask) << (n)))
#define CLEAR_BIT(value, n) ((value) &= ~(1ull << (n)))
#define CLEAR_BITS(value, mask, n) ((value) &= ~((mask) << (n)))
#define TOGGLE_BIT(value, n) ((value) ^= (1ull << (n)))
#define TOGGLE_BITS(value, mask, n) ((value) ^= ((mask) << (n)))
#define CHECK_BIT(value, n) (((value) & (1ull << (n))))
#define SET_BITMASK(value, mask) ((value) |= (mask))
#define CLEAR_BITMASK(value, mask) ((value) &= (~(mask)))
#define TOGGLE_BITMASK(value, mask) ((value) ^= (mask))
template <typename T>
void printBitNumber(T number)
{
unsigned int bitSize = sizeof(number) * 8;
T mask = (1ull) << (bitSize - 1);
printf("%d", (number & mask) == mask);
mask = (1ull) << (bitSize - 2);
for (int i = 1; i < bitSize; i++)
{
printf("%d", (number & mask) == mask);
mask >>= 1;
if (i % 8 == 7) printf(" ");
}
putchar('\n');
}
int main(void)
{
ll number = 0x1234123412341234;
printBitNumber(number);
SET_BIT(number, 63);
SET_BIT(number, 62);
SET_BIT(number, 61);
SET_BIT(number, 60);
CLEAR_BIT(number, 59);
CLEAR_BIT(number, 58);
CLEAR_BIT(number, 57);
CLEAR_BIT(number, 56);
TOGGLE_BIT(number, 55);
TOGGLE_BIT(number, 54);
TOGGLE_BIT(number, 53);
TOGGLE_BIT(number, 52);
printBitNumber(number);
printf("%lld\n", CHECK_BIT(number, 51));
printf("%lld\n", CHECK_BIT(number, 50));
printf("%lld\n", CHECK_BIT(number, 49));
printf("%lld\n", CHECK_BIT(number, 48));
printf("%d", GET_BIT(number, 51));
printf("%d", GET_BIT(number, 50));
printf("%d", GET_BIT(number, 49));
printf("%d", GET_BIT(number, 48));
putchar('\n');
putchar('\n');
/* --------------------------------------- */
ll mask = 0xFF00000000001200;
printf("mask : "); printBitNumber(mask);
putchar('\n');
number = 0x1234123412341234;
printf("before : "); printBitNumber(number);
SET_BITMASK(number, mask);
printf("after : "); printBitNumber(number);
putchar('\n');
number = 0x1234123412341234;
printf("before : "); printBitNumber(number);
CLEAR_BITMASK(number, mask);
printf("after : "); printBitNumber(number);
putchar('\n');
number = 0x1234123412341234;
printf("before : "); printBitNumber(number);
TOGGLE_BITMASK(number, mask);
printf("after : "); printBitNumber(number);
putchar('\n');
return 0;
}
'개발 > C, C++' 카테고리의 다른 글
C, C++ - 비트 연산으로 2의 제곱수 처리하기 (0) | 2023.07.29 |
---|---|
C, C++ - 임시 변수 없이 변수 바꾸기 (Swap Two Numbers without using the Third Variable) (0) | 2023.07.29 |
C, C++ - 비트 단위로 출력하기 (Print Bit) (0) | 2023.06.03 |
C++ - 튜플로 여러 값 반환하기 (Returning Multiple Values Using Tuple) (0) | 2023.04.15 |
scanf를 이용해 정수 1칸 입력 받기 (0) | 2023.03.26 |
댓글