오른쪽 시프트 연산자의 흥미로운 동작
오른쪽 시프트 연산자(>>)는 큰 오른쪽 시프트 값을 처리할 때 독특한 동작을 나타냅니다. 다음 프로그램을 고려해보세요:
#include
#include
int foo(int a, int b)
{
return a >> b;
}
int bar(uint64_t a, int b)
{
return a >> b;
}
int main()
{
std::cout > 32: " > 32) > (int)32: " > (int)32) foo(1, 32)의 예상 출력은 0이지만 놀랍게도 1을 반환합니다. 이는 다음 원인으로 인해 발생할 수 있습니다.
논리적 이동 대 산술 Shift
x86/x86-64 아키텍처에서 오른쪽 시프트 연산자는 실제로 논리적 오른쪽 시프트를 수행합니다. 즉, 비워진 비트를 0으로 채웁니다. 왼쪽 피연산자의 부호. 동작은 a >>>를 사용하는 것과 유사합니다. 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에서는 다른 구현이 사용될 수 있습니다. 정의되지 않은 동작으로 인해 피연산자 너비보다 크거나 같은 개수의 오른쪽 시프트 결과는 이식 가능한 코드에서 피해야 합니다.
부인 성명: 제공된 모든 리소스는 부분적으로 인터넷에서 가져온 것입니다. 귀하의 저작권이나 기타 권리 및 이익이 침해된 경우 자세한 이유를 설명하고 저작권 또는 권리 및 이익에 대한 증거를 제공한 후 이메일([email protected])로 보내주십시오. 최대한 빨리 처리해 드리겠습니다.
Copyright© 2022 湘ICP备2022001581号-3