본문 바로가기

C, Cpp

특정 위치의 비트를 끄기

이번에는 임의의 정수 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