2012-03-29 2 views
1

내가 C에서 비트-만지작 만지작하고, 나는 흥미로운 출력을 가로 질러 온과 혼동 :비트 만지작 -이 프로그램의 출력 그래서

int main() 
{ 
    int a = 0x00FF00FF; 
    int b = 0xFFFF0000; 

    int res = (~b & a); 

    printf("%.8X\n", (res << 8) | (b >> 24)); 
} 

그리고이 문장의 출력은 다음과 같습니다

FFFFFFFF

나는 수 출력을 예상

0000FFFF

왜 그렇습니까? 여기서 비트 시프 팅으로 뭔가를 놓치고 있습니까?

답변

5

TLDR : 정수 b가 음수이므로 오른쪽으로 시프트하면 최상위 비트 (즉, 1)의 값이 동일하게 유지됩니다. 따라서 b 위치를 24 위치만큼 이동하면 0xFFFFFFFF가됩니다.

긴 설명 :

귀하의 정수는 32 비트 이상 및 부호있는 정수는 2의 보수로 표현되어있는 플랫폼에 가정은 부호있는 정수 변수에 할당 된 0xFFFF0000은 음수이다. int가 32 비트보다 길면 0xFFFF0000은 부호가 먼저 확장되고 여전히 음수가됩니다. 음수 쉬프팅

적합한 표준 (C99/N1256, 섹션 6.5.7.5)에 의해 정의 된 구현 :

>> E1 E2의 결과 E1 E2 오른쪽 시프트 비트 위치이다. [...] E1 에 부호가있는 유형과 음수 값이있는 경우 결과 값은 구현이 정의됩니다.

즉, 특정 컴파일러가 특정 상황에서 일어나는 일을 선택할 수 있지만 컴파일러 설명서에서 그 효과를 알아야합니다.

많은 프로세서에서 두 세트의 시프트 명령어, 즉 논리 시프트와 산술 시프트가 발생하는 경향이 있습니다. 논리 시프트 오른쪽은 비트를 시프트하고 노출 된 비트를 0으로 채 웁니다. 산술 시프트가 오른쪽으로 (2의 보수를 다시 가정하면) 노출 된 비트가 최상위 비트의 동일한 비트 값으로 채워 지므로 시프트를 2로 나눈 값과 일치하는 결과가됩니다 (예 : -4 >> 1 == 0xFFFFFFFC >> 1 == 0xFFFFFFFE == -2)

귀하의 경우에는 컴파일러 구현자가 부호가있는 정수에 적용될 때 산술 시프트를 사용하기 때문에 음수 오른쪽 값은 음수 값을 유지합니다. 0xFFFF0000 비트 패턴의 관점에서 >> 24는 0xFFFFFFFF를 제공합니다.

당신이하고있는 일을 절대적으로 확신하지 않는 한, 내부 표현이 안전함을 비트 집합으로 취급 할 수 있으므로 부호없는 유형에만 비트 연산을 수행하는 것이 가장 좋습니다. 또한이 경우 사용하는 숫자 값에 부호없는 접미사를 추가하여 부호가 없는지 확인해야 할 수도 있습니다.

+0

흥미 음수 우 패드 서명. 나는 당신이 비트 - 시프트 할 때 그 사인이 남아 있다는 사실을 어떻게 놓쳤는 지 궁금하다. –

+0

@ RichardJ.RossIII : 부호가있는 정수에만 해당되므로 어쩌면 눈치 채지 못할 수도 있습니다. 또는 문제가되는 올바른 범위의 정수 (2의 보수 표현 및 음수 값)를 가진 적이 없었을 것입니다. – tinman

+0

@ RichardJ.RossIII : 0'' ~ 0'''의 보수를 바꾸려고 노력했습니다. 더 좋은 방법은'~ 0u >> x'였습니다. – Morpfh

0

황금률 : 절대 부호있는 숫자와 비트 연산자를 혼용하지 마십시오.

모든 int를 부호없는 정수로 변경하십시오.마찬가지로 예방책으로 모든 리터럴도 서명되지 않은 것으로 변경하십시오.

#include <stdint.h> 

uint32_t a = 0x00FF00FFu; 
uint32_t b = 0xFFFF0000u; 

uint32_t res = (~b & a); 
+1

골든 규칙 even : 부호있는 유형의 비트 연산자를 사용하지 않습니다. – ouah

2

우측 - 시프 팅 음수 값 (추천 b) 두 가지 다른 방법으로 정의 될 수있다 : (a 제로 이동량 때 양수를 산출) 왼쪽 제로와 가치를 패딩하는 논리 시프트을 , 산술 시프트으로 값을 채 웁니다 (항상 음수를 나타냅니다). C에서 사용되는 정의는 구현에 따라 정의되며 컴파일러는 산술 시프트를 사용합니다. 따라서 b >> 240xFFFFFFFF입니다.

1

B >> 24 0xFFFFFFFF로 제공

List = (res << 8) | (b >> 24) 
a  = 0x00FF00FF = 0000 0000 1111 1111 0000 0000 1111 1111 
b  = 0xFFFF0000 = 1111 1111 1111 1111 0000 0000 0000 0000 
~b  = 0x0000FFFF = 0000 0000 0000 0000 1111 1111 1111 1111 
~b & a = 0x000000FF = 0000 0000 0000 0000 0000 0000 1111 1111, = res 
res << 8 = 0x0000FF00 = 0000 0000 0000 0000 1111 1111 0000 0000 
b >> 24 = 0xFFFFFFFF = 1111 1111 1111 1111 1111 1111 1111 1111 
List  = 0xFFFFFFFF = 1111 1111 1111 1111 1111 1111 1111 1111 
관련 문제