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

C, C++ - 비트 단위로 출력하기 (Print Bit)

by 피로물든딸기 2023. 6. 3.
반응형

C, C++ 전체 링크

삼성 C형 전체 링크

 

아래와 같이 %x 옵션을 이용하면 4비트 (0 ~ F)로 값을 출력할 수 있다.

#include <stdio.h>

typedef unsigned long long int ull;

int main(void)
{
	ull h = 1023;
	printf("0x%08X\n", h);
	return 0;
}

 

이제 변수가 주어질 때, 1 비트 단위로 출력하는 함수를 만들어보자.

printBitNumber를 템플릿을 이용해서 만들고 mask를 이용해 최상위 비트부터 하나씩 내려가면서 출력한다.

// signed에서 error 발생

#include <stdio.h>

typedef unsigned char uc;
typedef unsigned short us;
typedef unsigned int ui;
typedef long long int ll;
typedef unsigned long long int ull;

template <typename T>
void printBitNumber(T number)
{
	unsigned int bitSize = sizeof(number) * 8;

	T mask = (1ull) << (bitSize - 1);
	for (int i = 0; i < bitSize; i++)
	{
		printf("%d", (number & mask) == mask);
		mask >>= 1;
		if (i % 8 == 7) printf(" ");
	}
	putchar('\n');
}

int main(void)
{
	char a = 12;
	uc b = 12;
	short c = 500;
	us d = 500;
	int e = 1000;
	ui f = 1000;
	ll g = 1023;
	ull h = 1023;

	printBitNumber(a);
	printBitNumber(b);
	printBitNumber(c);
	printBitNumber(d);
	printBitNumber(e);
	printBitNumber(f);
	printBitNumber(g);
	printBitNumber(h);

	return 0;
}

 

출력을 해보면 signed type은 비정상적으로 출력된다.

 

원인을 알아보기 위해 signedunsigned int를 1 << 31로 만들고 비트를 오른쪽으로 한 칸 옮겨보자.

	signed int integer = 1 << 31;
	integer >>= 1;

	unsigned int unsignedInteger = 1 << 31;
	unsignedInteger >>= 1;

	printBitNumber(integer);
	printBitNumber(unsignedInteger);

 

제대로 출력되는 printBitNumber 함수라면 signed int인 경우 최상위 비트가 1인 경우 1이 남아있는 상태가 된다.

 

3130으로 변경해서 다시 출력해보자.

	signed int integer = 1 << 30;
	integer >>= 1;

	unsigned int unsignedInteger = 1 << 30;
	unsignedInteger >>= 1;

	printBitNumber(integer);
	printBitNumber(unsignedInteger);

 

이 경우에는 같은 결과가 나온다.

 

따라서 아래의 함수에서 최상위 비트만 따로 출력하고, bitSize - 2부터 다시 시작하도록 코드를 보완하면 된다.

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');
}

 

최종 코드는 다음과 같다.

#include <stdio.h>

typedef unsigned char uc;
typedef unsigned short us;
typedef unsigned int ui;
typedef long long int ll;
typedef unsigned long long int ull;

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)
{
	char a = 12;
	uc b = 12;
	short c = 500;
	us d = 500;
	int e = 1000;
	ui f = 1000;
	ll g = 1023;
	ull h = 1023;

	printBitNumber(a);
	printBitNumber(b);
	printBitNumber(c);
	printBitNumber(d);
	printBitNumber(e);
	printBitNumber(f);
	printBitNumber(g);
	printBitNumber(h);

	return 0;
}


bitset을 이용하는 방법

 

bitset을 이용하면 조금 더 간단히 출력할 수 있다.

다만 8칸씩 띄우는 것은 따로 구현을 해야한다.

#include <stdio.h>
#include <iostream>
#include <bitset>

using namespace std;

typedef unsigned char uc;
typedef unsigned short us;
typedef unsigned int ui;
typedef long long int ll;
typedef unsigned long long int ull;

int main(void)
{
	char a = 12;
	uc b = 12;
	short c = 500;
	us d = 500;
	int e = 1000;
	ui f = 1000;
	ll g = 1023;
	ull h = 1023;

	cout << bitset<sizeof(a) * 8>(a) << endl;
	cout << bitset<sizeof(b) * 8>(b) << endl;
	cout << bitset<sizeof(c) * 8>(c) << endl;
	cout << bitset<sizeof(d) * 8>(d) << endl;
	cout << bitset<sizeof(e) * 8>(e) << endl;
	cout << bitset<sizeof(f) * 8>(f) << endl;
	cout << bitset<sizeof(g) * 8>(g) << endl;
	cout << bitset<sizeof(h) * 8>(h) << endl;

	return 0;
}

 

bitset<크기>를 이용하면 해당 크기에 맞게 비트를 출력한다.

반응형

댓글