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

C, C++ - 비트 교환 (Change Some Bits)

by 피로물든딸기 2023. 8. 15.
반응형

C, C++ 전체 링크

삼성 C형 전체 링크

 

참고

- 비트 연산 기본 매크로 함수

- 비트 단위로 출력하기

 

1. char 타입 4bit 교환

2. 4bit 단위로 교환

3. 1bit 교환


char 타입 4bit 교환

 

char는 1byte = 8bit이므로 아래와 같이 4bit씩 양 옆으로 옮겨주면 비트가 교환된다.

예를 들어 char a = 0xA9라면 0x9A가 된다.

typedef unsigned char uc;

uc change4Bit(unsigned char value)
{
	return (value << 4 | value >> 4);
}

 

전체 코드는 다음과 같다.

#include <stdio.h>

typedef unsigned char uc;

uc change4Bit(unsigned char value)
{
	return (value << 4 | value >> 4);
}

int main()
{
	uc a = 0xA9;
	uc b = change4Bit(a);

	printf("before : 0x%02X\n", a);
	printf("after  : 0x%02X\n", b);

	return 0;
}


4bit 교환

 

int는 4byte = 32bit로 이루어져 있고, 4bit가 8개로 이루어져 있다.

8개의 4bit 중 두 위치를 변경하는 코드는 비트 연산을 이용해서 아래와 같이 구현할 수 있다.

(입력되는 pos의 범위는 0 ~ 7)

typedef unsigned int ui;

ui change4Bit(ui value, ui pos1, ui pos2)
{
	pos1 *= 4;
	pos2 *= 4;

	ui mask1 = (0xF << (pos1));
	ui mask2 = (0xF << (pos2));
	ui bit1 = (value & mask1) >> pos1;
	ui bit2 = (value & mask2) >> pos2;

	value &= (~(mask1 | mask2));
	value |= ((bit1 << pos2) | (bit2 << pos1));

	return value;
}

 

아래의 코드를 실행해서 정상적으로 동작하는지 확인해 보자.

#include <stdio.h>

typedef unsigned int ui;

ui change4Bit(ui value, ui pos1, ui pos2)
{
	pos1 *= 4;
	pos2 *= 4;

	ui mask1 = (0xF << (pos1));
	ui mask2 = (0xF << (pos2));
	ui bit1 = (value & mask1) >> pos1;
	ui bit2 = (value & mask2) >> pos2;

	value &= (~(mask1 | mask2));
	value |= ((bit1 << pos2) | (bit2 << pos1));

	return value;
}

int main()
{
	int a = 0x76543210;

	printf("a : 0x%x\n", a);
	for (int i = 0; i < 8; i++)
	{
		for (int k = 0; k < 8; k++)
		{
			int b = change4Bit(a, i, k);
			printf("%d <-> %d 0x%08x\n", i, k, b);
		}
	}

	return 0;
}

 

long 타입의 경우는 0xFull을 추가해야 정상적으로 동작한다. (입력되는 pos의 범위는 0 ~ 15)

typedef unsigned long long int ull;

ull change4Bit(ull value, ull pos1, ull pos2)
{
	pos1 *= 4;
	pos2 *= 4;
	
	ull mask1 = (0xFull << (pos1));
	ull mask2 = (0xFull << (pos2));
	ull bit1 = (value & mask1) >> pos1;
	ull bit2 = (value & mask2) >> pos2;

	value &= (~(mask1 | mask2));
	value |= ((bit1 << pos2) | (bit2 << pos1));

	return value;
}

 

마찬가지로 아래 코드를 실행해서 테스트해 보자.

#include <stdio.h>

typedef unsigned long long int ull;

ull change4Bit(ull value, ull pos1, ull pos2)
{
	pos1 *= 4;
	pos2 *= 4;
	
	ull mask1 = (0xFull << (pos1));
	ull mask2 = (0xFull << (pos2));
	ull bit1 = (value & mask1) >> pos1;
	ull bit2 = (value & mask2) >> pos2;

	value &= (~(mask1 | mask2));
	value |= ((bit1 << pos2) | (bit2 << pos1));

	return value;
}

int main()
{
	ull a = 0xABCDEF98765432AB;

	for (int i = 0; i < 16; i++)
	{
		for (int k = 0; k < 16; k++)
		{
			ull b = change4Bit(a, i, k);
			printf("%d <-> %d 0x%llX\n", i, k, b);
		}
	}

	return 0;
}


1bit 교환

 

4bit 교환을 응용하여 1bit 단위로도 비트를 교환할 수 있다. 

int의 경우 입력되는 pos의 범위는 0 ~ 31이 된다.

typedef unsigned int ui;

ui change1Bit(ui value, ui pos1, ui pos2)
{
	ui mask1 = (0x1 << (pos1));
	ui mask2 = (0x1 << (pos2));
	ui bit1 = (value & mask1) >> pos1;
	ui bit2 = (value & mask2) >> pos2;

	value &= (~(mask1 | mask2));
	value |= ((bit1 << pos2) | (bit2 << pos1));

	return value;
}

 

정상적으로 1 비트가 교환되는지 확인해 보자.

#include <stdio.h>

typedef unsigned int ui;

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

ui change1Bit(ui value, ui pos1, ui pos2)
{
	ui mask1 = (0x1 << (pos1));
	ui mask2 = (0x1 << (pos2));
	ui bit1 = (value & mask1) >> pos1;
	ui bit2 = (value & mask2) >> pos2;

	value &= (~(mask1 | mask2));
	value |= ((bit1 << pos2) | (bit2 << pos1));

	return value;
}

int main()
{
	int a = 0x76543210;

	printf("a : 0x%x\n", a);
	for (int i = 0; i < 32; i++)
	{
		for (int k = 0; k < 32; k++)
		{
			int b = change1Bit(a, i, k);
			printf("%d <-> %d ", i, k);
			printBitNumber(b);
		}
	}

	return 0;
}

반응형

댓글