수색…


비고

비트 시프트 연산은 모든 프로세서 아키텍처에서 이식 가능하지 않으며, 서로 다른 프로세서가 서로 다른 비트 폭을 가질 수 있습니다. 다른 말로하면, 당신이 썼다면

int a = ~0;
int b = a << 1;

이 값은 64 비트 시스템과 32 비트 시스템에서 다를 수 있으며 x86 기반 프로세서에서 PIC 기반 프로세서로 달라질 수 있습니다.

Endian-ness는 비트 단위 연산 자체에서 고려 될 필요가 없습니다. 즉, 오른쪽 시프트 ( >> )는 비트를 최하위 비트쪽으로 이동시키고 XOR은 배타적 또는 비트를 수행합니다. 엔디안은 데이터 그 자체 만 고려해야합니다. 즉, 엔디안이 응용 프로그램에 문제가되는 경우 비트 연산과 상관없이 문제가됩니다.

& - 비트 AND

int a = 6;     // 0110b  (0x06)
int b = 10;    // 1010b  (0x0A)
int c = a & b; // 0010b  (0x02)

std::cout << "a = " << a << ", b = " << b << ", c = " << c << std::endl;

산출

a = 6, b = 10, c = 2

현명한 비트 AND 비트 레벨에서 작동하며 다음과 같은 부울 진실 테이블을 사용합니다 :

TRUE  AND TRUE  = TRUE
TRUE  AND FALSE = FALSE
FALSE AND FALSE = FALSE

a ( 0110 )에 대한 이진 값과 b ( 1010 )에 대한 이진 값을 AND 연산하면 0010 의 이진 값을 얻습니다.

int a = 0 1 1 0
int b = 1 0 1 0 &
        ---------
int c = 0 0 1 0

비트 현명한 할당 연산자 &= 를 사용하여 특별히 지정하지 않는 한 비트 현명한 AND는 원래 값의 값을 변경하지 않습니다.

int a = 5;  // 0101b  (0x05)
a &= 10;    // a = 0101b & 1010b

| - 비트 OR

int a = 5;     // 0101b  (0x05)
int b = 12;    // 1100b  (0x0C)
int c = a | b; // 1101b  (0x0D)

std::cout << "a = " << a << ", b = " << b << ", c = " << c << std::endl;

산출

a = 5, b = 12, c = 13

비트 단위 OR 은 비트 수준에서 작동하며 다음 부울 진리표를 사용합니다.

true OR true = true
true OR false = true
false OR false = false

a ( 0101 )에 대한 이진 값과 b ( 1100 )에 대한 이진 값을 OR 연산하면 이진 값 1101 .

int a = 0 1 0 1
int b = 1 1 0 0 |
        ---------
int c = 1 1 0 1

비트 현명한 할당 연산자 연산자 인 |= 을 사용하여 명시 적으로 할당하지 않는 한 비트 단위 OR은 원래 값의 값을 변경하지 않습니다.

int a = 5;  // 0101b  (0x05)
a |= 12;    // a = 0101b | 1101b

^ - 비트 XOR (배타적 논리합)

int a = 5;     // 0101b  (0x05)
int b = 9;     // 1001b  (0x09)
int c = a ^ b; // 1100b  (0x0C)

std::cout << "a = " << a << ", b = " << b << ", c = " << c << std::endl;

산출

a = 5, b = 9, c = 12

비트 단위 XOR (배타적 XOR )은 비트 수준에서 작동하며 다음 부울 진리표를 사용합니다.

true OR true = false
true OR false = true
false OR false = false

XOR 연산을 사용하면 true OR true = falsetrue AND/OR true = true 연산과 true AND/OR true = true 이므로 배타적 논리합 연산이 true AND/OR true = true 합니다.

이를 사용하여 a ( 0101 )에 대한 이진 값과 b ( 1001 )에 대한 이진 값을 XOR 할 때 이진 값 1100 얻습니다.

int a = 0 1 0 1
int b = 1 0 0 1 ^
        ---------
int c = 1 1 0 0

비트 현명한 배정 연산자 ^= 를 사용하여 특별히 지정하지 않는 한 비트 현명한 XOR은 원래 값의 값을 변경하지 않습니다.

int a = 5;  // 0101b  (0x05)
a ^= 9;    // a = 0101b ^ 1001b

비트 방식의 XOR은 다양한 방식으로 활용 될 수 있으며 암호화 및 압축을 위해 비트 마스크 연산에 종종 사용됩니다.

참고 : 다음 예제는 좋은 트릭의 예로 자주 표시됩니다. 그러나 프로덕션 코드에는 사용하면 안됩니다 std::swap() 같은 결과를 얻으려면 std::swap() 이 더 좋습니다).

또한 XOR 연산을 사용하여 임시없이 두 변수를 스왑 할 수 있습니다.

int a = 42;
int b = 64;

// XOR swap
a ^= b;
b ^= a;
a ^= b;

std::cout << "a = " << a << ", b = " << b << "\n";

이것을 생산하려면 수표를 사용하여 사용할 수 있는지 확인해야합니다.

void doXORSwap(int& a, int& b)
{
    // Need to add a check to make sure you are not swapping the same
    // variable with itself. Otherwise it will zero the value.
    if (&a != &b)
    {
        // XOR swap
        a ^= b;
        b ^= a;
        a ^= b;
    }
}

따라서 고립 된 멋진 트릭처럼 보일지라도 실제 코드에서는 유용하지 않습니다. xor는 기본 논리 연산이 아니라 다른 연산자의 조합입니다. a ^ c = ~ (a & c) & (a | c)

또한 2015+ 컴파일러 변수는 바이너리로 할당 될 수 있습니다 :

int cn=0b0111;

~ ~ 비트 NOT (단항)

unsigned char a = 234;  // 1110 1010b  (0xEA)
unsigned char b = ~a;   // 0001 0101b  (0x15)

std::cout << "a = " << static_cast<int>(a) <<
             ", b = " << static_cast<int>(b) << std::endl;

산출

a = 234, b = 21

조금 현명한 NOT (unary complement)은 비트 레벨에서 작동하고 각 비트를 단순히 플립합니다. 그것이라면 1 ,으로 바뀌 0 은 A의 경우, 0 , 그것으로 바뀌 1 . 비트 현명한 NOT은 특정 유형의 최대 값에 대해 값을 배타적으로 비교하는 것과 동일한 효과를냅니다.

unsigned char a = 234;  // 1110 1010b  (0xEA)
unsigned char b = ~a;   // 0001 0101b  (0x15)
unsigned char c = a ^ ~0;

비트 현명한 NOT은 또한 특정 적분 유형에 대한 최대 값을 확인하는 편리한 방법 일 수 있습니다.

unsigned int i = ~0;
unsigned char c = ~0;

std::cout << "max uint = " << i << std::endl <<
             "max uchar = " << static_cast<short>(c) << std::endl;

비트 현명한 NOT은 원래 값의 값을 변경하지 않고 복합 대입 연산자를 가지지 않으므로 a ~= 10 과 같이 할 수 없습니다.

비트 현명 NOT ( ~ )을 논리적 NOT ( ! )과 혼동해서는 안됩니다. 조금 현명한 NOT은 각 비트를 뒤집을 것이고, 논리 NOT은 전체 값을 사용하여 작업을 수행합니다 (!1) != (~1) 즉, (!1) != (~1)

<< - 왼쪽 시프트

int a = 1;      // 0001b
int b = a << 1; // 0010b

std::cout << "a = " << a << ", b = " << b << std::endl;

산출

a = 1, b = 2

왼쪽 비트 현명한 이동은 왼쪽 값 ( a )의 비트를 오른쪽 ( 1 )에 지정된 숫자로 이동시켜 기본적으로 최하위 비트를 0으로 채우므로 값 5 (이진 0000 0101 )가 왼쪽으로 시프트됩니다 4 배 (예 : 5 << 4 )는 80 (2 진수 0101 0000 )의 값을 산출합니다. 값을 왼쪽 1 시간으로 이동하는 것은 값에 2를 곱하는 것과 같습니다. 예를 들면 다음과 같습니다.

int a = 7;
while (a < 200) {
    std::cout << "a = " << a << std::endl;
    a <<= 1;
}

a = 7;
while (a < 200) {
    std::cout << "a = " << a << std::endl;
    a *= 2;
}

그러나 왼쪽 시프트 연산은 부호 비트를 포함하여 모든 비트를 왼쪽으로 시프트 할 것입니다 (예 :

int a = 2147483647; // 0111 1111 1111 1111 1111 1111 1111 1111
int b = a << 1;     // 1111 1111 1111 1111 1111 1111 1111 1110

std::cout << "a = " << a << ", b = " << b << std::endl;

가능한 출력 : a = 2147483647, b = -2

일부 컴파일러에서는 예상 된 결과를 얻을 수 있지만 부호 비트가 영향을 받도록 부호있는 숫자를 왼쪽으로 이동하면 결과는 정의되지 않습니다 . 시프트하려는 비트 수가 음수이거나 왼쪽의 유형이 보유 할 수있는 비트 수보다 큰 경우에는 정의되지 않습니다 . 예를 들면 다음과 같습니다.

int a = 1;
int b = a << -1;  // undefined behavior
char c = a << 20; // undefined behavior

비트 현명한 할당 연산자 연산자 <<= 를 사용하여 특별히 지정하지 않는 한 비트 현 왼쪽 쉬프트는 원래 값의 값을 변경하지 않습니다.

int a = 5;  // 0101b
a <<= 1;    // a = a << 1;

>> - 오른쪽 교대

int a = 2;      // 0010b
int b = a >> 1; // 0001b

std::cout << "a = " << a << ", b = " << b << std::endl;

산출

a = 2, b = 1

오른쪽 비트 현명한 이동은 왼쪽 값 ( a )의 비트를 오른쪽 ( 1 )에 지정된 숫자로 이동시킵니다. 오른쪽 시프트의 연산은 표준이지만 부호있는 음수 의 오른쪽 시프트 비트는 구현 정의 이므로 휴대 가능함을 보장 할 수 없습니다. 예를 들면 다음과 같습니다.

int a = -2;    
int b = a >> 1; // the value of b will be depend on the compiler

또한 시프트 할 비트 수가 음수 인 경우 정의되지 않습니다 (예 :

int a = 1;
int b = a >> -1;  // undefined behavior

비트 현명한 대입 연산자 >>= 를 사용하여 특별히 지정하지 않는 한 비트 현명한 오른쪽 시프트는 원래 값의 값을 변경하지 않습니다.

int a = 2;  // 0010b
a >>= 1;    // a = a >> 1;


Modified text is an extract of the original Stack Overflow Documentation
아래 라이선스 CC BY-SA 3.0
와 제휴하지 않음 Stack Overflow