본문 바로가기
개발/C, C++

C, C++ - 비트 연산 기본 매크로 함수 (bit macro : get, set, clear, toggle, check)

by 피로물든딸기 2023. 7. 29.
반응형

C, C++ 전체 링크

삼성 C형 전체 링크

 

비트 연산 기본에 대해서 알아보자. (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;
}
반응형

댓글