비트 조작

비트 조작



비트 조작은 다양한 문제에 사용됩니다. 때때로 질문은 명시적으로 비트 조작을 요구합니다. 다른 경우에는 코드를 최적화하는 유용한 기술일 뿐입니다.

비트 팩트 및 요령



또는




x | 0s = x
x | 1s = 1
x | x = x


그리고




x & 0s = 0
x & 1s = x
x & x = x


XOR




x ^ 0s = x
x ^ 1s = ~x
x ^ x = 0


2의 보수와 음수



컴퓨터는 일반적으로 정수를 2의 보수 표현으로 저장합니다. 양수는 그 자체로 표시되는 반면 음수는 절대값의 2의 보수로 표시됩니다(부호 비트에 1이 음수임을 나타냄).

N 비트 숫자의 2의 보수(여기서 N은 부호 비트를 제외한 숫자에 사용된 비트 수)는 2^N에 대한 숫자의 보수입니다.

4비트 숫자를 가정하고 -3를 나타냅니다. -3에 대한 2^3의 보수는 5입니다. 이진수에서 5101입니다. 따라서 -3는 4비트 숫자로 1101이며 첫 번째 비트가 부호 비트입니다.

즉, -K를 N비트 수로 이진수로 표현하면 concat(1, 2^(N-1) - K) 입니다.

이것을 보는 또 다른 방법은 양의 표현에서 비트를 반전시킨 다음 1를 추가하는 것입니다. 이진수에서 3011입니다. get 100 으로 비트를 뒤집고 get 1101 를 추가한 다음 부호 비트 1 를 앞에 추가하여 1101 를 얻습니다.

논리 및 산술 시프트



단일 Bit는 Storage의 기본 단위로 1 또는 0을 저장합니다. 따라서 특정 유형의 값에서 비트가 왼쪽 또는 오른쪽으로 이동함에 따라 해당 값이 변경됩니다. C 언어에서 값의 비트 이동은 왼쪽 또는 오른쪽 시프트 연산자를 사용하여 수행됩니다. 이러한 연산자는 부호 있는 형식 또는 부호 없는 형식의 정수 데이터 형식 변수 값의 개별 비트에 대해 작동합니다. 문자는 내부적으로 정수이므로 이러한 연산자를 사용할 수 있습니다.

왼쪽 시프트 연산자는 <<로 표시되고 오른쪽 시프트는 >>로 표시됩니다. 이러한 연산자는 이진 연산자이며 양쪽에 두 개의 피연산자가 필요하고 둘 다 정수여야 합니다.

논리적 이동



이동은 부호 없는 정수에서 어느 방향으로든 수행될 때 논리라고 합니다. 논리적 이동에서 한쪽으로 이동하는 동안 빈 슬롯은 0으로 채워집니다.

int main(void)
{
    unsigned int x = 8;
    unsigned int y = 8;

    x >>= 1;    // Right Shift by 1
    y <<= 1;    // Left  Shift by 1

    printf("After Right Shift, x = %d \n", x);
    printf("After Left  Shift, y = %d \n", y);
}


산출:

After Right Shift, x = 4 
After Left  Shift, y = 16 


  • 값을 오른쪽으로 n비트 이동하면 값을 2의 n제곱으로 나누는 효과가 있습니다.
  • 값을 왼쪽으로 n비트 이동하면 값에 2의 거듭제곱 n을 곱하는 효과가 있습니다.

  • 산술 시프트



    산술 및 논리 왼쪽 시프트는 동일합니다. 오른쪽 이동만 다르고 음수 값만 다릅니다. 따라서 부호 있는 값을 오른쪽으로 이동하는 프로그램은 본질적으로 이식성이 없습니다.

    산술 오른쪽 시프트



    산술 오른쪽 이동에서는 값을 오른쪽으로 이동하지만 sig 비트의 값으로 새 비트를 채웁니다.

    부호 없는 숫자를 계속 오른쪽으로 이동하면 최상위 비트에서 반복적으로 0을 이동하므로 0가 됩니다. 부호 있는 음수의 경우 1을 최상위 비트로 이동하기 때문에 -1가 됩니다.

    일반적인 비트 작업



    비트 설정



    기능:

    int SetBit(int Num, int BitIndex)
    {
        return num | (1 << BitIndex);
    }
    


    매크로:

    #define     SET_BIT(Num, BitIndex)      (Num |= (1 << BitIndex))
    


    클리어 비트



    기능:

    int ClearBit(int Num, int BitIndex)
    {
        int mask = ~(1 << BitIndex);
    
        return Num & mask;
    } 
    


    매크로:

    #define     CLR_BIT(Num, BitIndex)      (Num &= (~(1 << BitIndex)))
    


    BitIndex(포함)를 통해 MSB에서 모든 비트를 지우려면:

    int ClearBitsMSBthroughBitIndex(int Num, int BitIndex)
    {
        int mask = (1 << BitIndex) - 1;
    
        return Num & mask;
    }
    


    LSB(포함)를 통해 BitIndex에서 모든 비트를 지우려면:

    int ClearBitsBitIndexthroughLSB(int Num, int BitIndex)
    {
        int mask = (-1 << (BitIndex + 1));
    
        return Num & mask;
    }
    


    비트 받기



    기능:

    int GetBit(int Num, int BitIndex)
    {
        return Num & (1 << BitIndex);
    }
    


    매크로:

    #define     GET_BIT(Num, BitIndex)      (Num &= (1 << BitIndex))
    


    토글 비트



    기능:

    int ToggleBit(int Num, int BitIndex)
    {
        return Num ^ (1 << BitIndex);
    }
    


    매크로:

    #define     TGL_BIT(Num, BitIndex)      (Num ^= (1 << BitIndex))
    


    업데이트 비트



    i번째 비트를 값으로 설정하려면 먼저 해당 위치에서 비트를 지운 다음 의도한 값을 이동합니다.

    기능:

    int UpdateBit(int Num, int BitIndex, int Value)
    {
        int mask = ~(1 << BitIndex);
    
        Num &= mask;
    
        Num |= (Value << BitIndex);
    }
    


    매크로:

    #define     UPDATE_BIT(Num, BitIndex, Value)    ((Num = (Num & (~(1 << BitIndex)) | (Value << BitIndex))))
    

    좋은 웹페이지 즐겨찾기