이번에는 임의의 정수 n 에서, k번째 비트만 바꿔버리는 방법에 대해 알아보겠습니다.
이때 k번째 비트는 2진수 n의 맨 뒤에서부터 세는 점에 유의해주시기 바랍니다.
예를 들어, n= 93 에서 k = 4 번째 비트만 0으로 바꾸는 경우를 살펴보자.
n을 이진수로 나타내면 1011101이다.
1 | 0 | 1 | 1 | 1 | 0 | 1 |
n에 적용할 비트마스크를 mask라고 하자.
mask는 1을 왼쪽으로 3( = k - 1)회 shift한 수 이고, 아래와 같다.
0 | 0 | 0 | 1 | 0 | 0 | 0 |
n과 mask 끼리 xor 연산을 하면, k번째 비트만 1에서 0으로 바뀐 것을 알 수 있다.
1 | 0 | 1 | 0 | 1 | 0 | 1 |
비트를 1에서0으로 끄는 것 대신, 그 반대의 경우를 생각해보자.
n = 85 에서, 2번째 비트(k = 2)를 0에서 1로 바꿔보자.
n을 이진수로 나타내면 1010101이다.
1 | 0 | 1 | 1 | 1 | 0 | 1 |
2번째 비트(= 0)를 1로 만들기 위한 비트마스크를 만드는 방법은, 앞서 살펴본 경우와 동일하다.
0 | 0 | 0 | 0 | 0 | 1 | 0 |
n과 위의 비트마스크 끼리 xor 대신 or 연산을 하면, 2번째 비트를 1로 반전할 수 있다.
1 | 0 | 1 | 0 | 1 | 1 | 1 |
위의 과정을 코드로 옮기면 아래와 같이 표현할 수 있다.
#include <stdio.h>
int is_bit_set(unsigned char value, int position){
return (value & (1 << (position - 1))) != 0;
}
unsigned char set_bit(unsigned char value, int position){
return value | (1 << (position - 1));
}
unsigned char clear_bit(unsigned char value, int position) {
return value ^ (1 << (position-1));
// (1 << (position-1)): 비트마스크
// position번째 비트(1)은 1과 xor -> 0으로 변경
}
int main(void)
{
unsigned char value = 0b00001000;
if (is_bit_set(value, 3)) {
printf("3rd bit is set \n");
}else{
printf("3rd bit is not set \n");
}
value = set_bit(value, 2);
printf("Value after changing 2nd bit: %d \n", value);
printf("Value after turning 2nd bit to zero: %d \n", clear_bit(value, 2));
return 0;
}
위의 코드를 약간 변형시켜서, 사용자로부터 숫자 n과 비트를 반전시킬 위치인 k를 입력받는 코드도 만들어보았다.
// 참고사이트: https://www.geeksforgeeks.org/set-clear-and-toggle-a-given-bit-of-a-number-in-c/
// https://developing-kestrel.tistory.com/6
#include <stdio.h>
unsigned char clear_bit(unsigned char value, int position) {
return value ^ (1 << (position-1));
// (1 << (position-1)): 비트마스크
// position번째 비트(1)은 1과 xor -> 0으로 변경
}
unsigned char shift_to_one(unsigned char value, int position) {
return value | (1 << (position-1));
// (1 << (position-1)): 비트마스크
// position번째 비트(0)은 1과 or -> 1으로 변경
}
int main(void)
{
int n = 0;
int k = 0;
printf("Target integer: ");
scanf("%d", &n);
printf("Which bit to reverse: ");
scanf("%d", &k);
// Do & of n with a number with all set bits except
// the k'th bit
int to_zer0 = clear_bit(n, k); // k번째 비트를 0로 바꾼 결과
if (to_zer0 == n){ // 만약 끄려는 k번째 비트가 0 -> 결과는 n이랑 차이 없음
printf("turn on bit (change to 1): %d \n", shift_to_one(n, k)); // k번째 비트를 (0에서) 1로 반전한 결과를 출력
}else{ // 만약 끄려는 k번째 비트가 1
printf("turn off bit (change to 0): %d \n", to_zer0); // k번째 비트를 (1에서) 0로 반전한 결과를 출력
}
return 0;
}
'C, Cpp' 카테고리의 다른 글
C언어를 기계어로 변환해보기 (0) | 2023.09.14 |
---|---|
오버플로우 ? 언더플로우 (0) | 2023.09.13 |
C의 자료형 별 크기 (0) | 2023.09.12 |