오른쪽 시프트 연산자의 흥미로운 동작
오른쪽 시프트 연산자(>>)는 큰 오른쪽 시프트 값을 처리할 때 특이한 동작을 나타냅니다. . 다음 프로그램을 고려해 보세요.
<code class="c++">#include <iostream> #include <stdint.h> int foo(int a, int b) { return a >> b; } int bar(uint64_t a, int b) { return a >> b; } int main() { std::cout << "foo(1, 32): " << foo(1, 32) << std::endl; std::cout << "bar(1, 32): " << bar(1, 32) << std::endl; std::cout << "1 >> 32: " << (1 >> 32) << std::endl; //warning std::cout << "(int)1 >> (int)32: " << ((int)1 >> (int)32) << std::endl; //warning }
foo(1, 32)의 예상 출력은 0이지만 놀랍게도 1을 반환합니다. 이는 다음과 같은 이유 때문일 수 있습니다.
논리적 시프트 대 산술 시프트
x86/x86-64 아키텍처에서 오른쪽 시프트 연산자는 실제로 논리적 오른쪽 시프트를 수행합니다. 왼쪽 피연산자의 부호에 관계없이 비트가 0입니다. 동작은 >>>를 사용하는 것과 유사합니다. b.
컴파일러 최적화
foo(1, 32)의 경우 값 32가 int로 캐스팅되어 효과적으로 32비트로 잘립니다. int가 보유할 수 있는 최대값은 231-1이므로 오른쪽 시프트는 본질적으로 >>> (32 % 32), 이는 0으로 평가됩니다.
정의되지 않은 동작
관련 C 표준에서는 개수가 더 큰 오른쪽 시프트에 대해 "동작이 정의되지 않음"이라고 명시합니다. 승격된 왼쪽 피연산자의 너비보다 크거나 같습니다. 이 경우, 1>> 32 및 (int)1>> (int)32의 개수가 32보다 크므로 예측할 수 없는 결과가 발생합니다.
bar(1, 32)와의 차이점
함수 bar는 64비트를 사용합니다. 너비가 32보다 큰 것이 보장되는 부호 없는 정수입니다. 따라서 bar의 오른쪽 시프트는 정의되지 않은 동작의 영향을 받지 않습니다.
결론
의 동작 큰 시프트 값을 처리할 때 오른쪽 시프트 연산자가 모호해집니다. x86/x86-64 아키텍처에서는 논리적 오른쪽 시프트가 수행되는 반면 ARM에서는 다른 구현이 사용될 수 있습니다. 정의되지 않은 동작으로 인해 피연산자 너비보다 크거나 같은 개수의 오른쪽 시프트 결과는 이식 가능한 코드에서 피해야 합니다.
위 내용은 ## 오른쪽 Shift 연산자가 큰 Shift 값에서 예기치 않은 동작을 나타내는 이유는 무엇입니까?의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!