2011-09-22 4 views
15

:오른쪽 시프트 및 부호있는 정수

(11111111 11111111 10000000 00000000) 

내 질문 :

sint32 word = (10000000 00000000 00000000 00000000); 
word >>= 16; 

은 다음과 같습니다 비트 필드와 word을 생산 모든 플랫폼 및 C++ 컴파일러에서이 동작을 신뢰할 수 있습니까?

답변

23

: INT34-C. Do not shift an expression by a negative number of bits or by greater than or equal to the number of bits that exist in the operand

비 규격 코드 예 (오른쪽 Shift)

E1 >> E2의 결과는 E1 오른쪽으로 이동 E2 비트 위치이다. E1에 부호없는 유형이 있거나 E1에 부호가있는 유형과 음수가 아닌 값이있는 경우 결과 값은 E1/2 E2의 몫의 정수 부분입니다.
Arithmetic (signed) shift
또는 논리 (부호) 시프트 :
Logical (unsigned) shift
이 비 대응 코드 예 E1 서명 된 유형 및 음의 값을 갖는 경우, 생성 된 값이 구현 정의 연산 일 수있다 시프트 (부호) 오른쪽 피연산자가 승격 된 왼쪽 피연산자의 너비보다 크거나 같은지 여부를 테스트하지 못하여 정의되지 않은 동작이 허용됩니다. 우측 시프트 연산으로 구현되는지 여부에 대한

unsigned int ui1; 
unsigned int ui2; 
unsigned int uresult; 

/* Initialize ui1 and ui2 */ 

uresult = ui1 >> ui2; 

메이커 가정 (부호) 또는 논리 시프트 (부호)은 시프트 취약성을 초래할 수있다. 추천 번호 INT13-C. Use bitwise operators only on unsigned operands을 참조하십시오.

+1

실제로이 문제에 초점을 맞춘 권장 사항이 없었습니까? 그 규칙의 이름에 기반하여, 여기에 적용되지 않기 때문에 ... 제공된 배경 정보 중 일부만 인용하면됩니다. –

12

아니요,이 동작에 의존 할 수 없습니다. 음수의 오른쪽 시프 팅 (예제에서 다루는 것으로 가정)은 구현 정의입니다.

+0

좋습니다. 컴파일러가이 방법을 사용하는 바이너리를 생성하면 대부분의 하드웨어에서 예상대로 작동합니까? –

+4

특정 아키텍처 용으로 컴파일하면 해당 아키텍처의 모든 구현에서 동일하게 작동합니다. 예를 들어, x86은 부호 확장 및 부호 확장 확장에 대해 다른 시프트 연산을 사용하며, 어느 것이 사용할 것인지 결정하는 컴파일러입니다. 아마도 다른 아키텍처에서는 전혀 작동하지 않을 것입니다 (이 동작뿐만 아니라 * 모든 것을 읽습니다). –

+0

이것은 끔찍한 ... – Claudiu

3

AFAIK 정수는 부호 확장으로 표현할 수 있습니다.이 경우 부호 확장은 0으로 채 웁니다. 그래서 당신은 이것에 의지 할 수 없습니다. 다음 링크에서

+0

당신 말이 맞아요. 표준은 2의 보완을 최적의 표현으로 만드는 몇 가지 요구 사항을 제시하지만 일반적으로 구현 된 방식으로 부호있는 정수를 표현할 수 있습니다. –

6

C++에서 아니요. 구현 및/또는 플랫폼에 따라 다릅니다.

다른 언어로는 예입니다. 예를 들어, Java에서 >> 연산자는 항상 가장 왼쪽 비트를 사용하여 항상 채우기 (따라서 기호를 유지)하도록 정확하게 정의됩니다. >>> 연산자는 0을 사용하여 채 웁니다. 따라서 신뢰할 수있는 동작을 원한다면 가능한 다른 옵션은 다른 언어로 변경하는 것입니다. (분명히 상황에 따라 옵션이 아닐 수도 있습니다.)

관련 문제