>`) C에서 32비트씩 이동할 때 예상치 못한 결과가 발생합니까? " />
오른쪽 시프트 연산자의 예상치 못한 동작(1>> 32)
프로그래밍 영역에서 오른쪽 시프트 연산자(>> )는 일반적으로 비트 단위 연산을 수행하는 데 사용됩니다. 특히 정수를 2의 거듭제곱으로 나누는 경우에는 다음 C 코드에서 볼 수 있듯이 더 큰 값으로 이동할 때 특이한 동작이 발생할 수 있습니다.
<code class="cpp">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 here std::cout << "(int)1 >> (int)32: " << ((int)1 >> (int)32) << std::endl; //warning here }
놀랍게도 , 이 프로그램의 출력은 예상치 못한 결과를 드러냅니다.
foo(1, 32): 1 // Should be 0 bar(1, 32): 0 1 >> 32: 0 (int)1 >> (int)32: 0</code>
이러한 결과의 근거는 CPU와 컴파일러의 내부 작동에 있습니다.
foo()의 동작 함수
foo() 함수에서는 캐스트 없이 시프트 연산이 수행되어 CPU가 논리적 오른쪽 시프트를 수행하게 됩니다. 많은 아키텍처에서 논리적 오른쪽 시프트는 > >(b % 32), b의 상위 비트를 효과적으로 무시합니다. 따라서 foo(1, 32)는 1>>0으로 평가되어 1을 산출합니다.
64비트 정수로의 형변환이 중요한 이유는 무엇입니까?
bar() 함수에는 64비트 부호 없는 정수가 제공되어 결과가 보장됩니다. b(32)가 피연산자(64)의 비트 수보다 작기 때문에 0이 됩니다. 그러나 b가 64로 변경되면 결과를 예측할 수 없게 되어 여전히 1이 나올 수 있습니다.
컴파일러 최적화
1의 경우 >> 32 및 (int)1>> (int)32, 컴파일러는 컴파일 타임에 이러한 상수 표현식을 최적화합니다. 표준은 개수가 음수이거나 피연산자 길이보다 크거나 같은 오른쪽 시프트에 대해 정의되지 않은 동작을 지정합니다. 32가 피연산자 길이를 초과하므로 컴파일러는 결과를 확인할 수 없으며 안전한 대체 값으로 0을 출력합니다.
CPU 관련 동작
오른쪽 시프트 구현 작업은 CPU마다 다를 수 있습니다. x86/x86-64 아키텍처에서 논리적 오른쪽 시프트는 사실상 >> (b % 32 또는 64), 모드에 따라 다릅니다. 그러나 ARM 프로세서에서 오른쪽 시프트 연산은 32보다 크거나 같은 시프트에 대해 0을 보장합니다.
결론
오른쪽 시프트 연산자로 작업할 때, 특히 시프트 수가 피연산자 길이를 초과하는 경우 잠재적인 정의되지 않은 동작을 고려합니다. 64비트 정수와 같은 더 넓은 정수 유형으로 변환하면 다양한 CPU 및 컴파일러에서 일관된 결과를 보장할 수 있습니다.
위 내용은 C에서 오른쪽 시프트 연산자(`>>`)가 32비트씩 이동할 때 예상치 못한 결과를 생성하는 이유는 무엇입니까?의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!