2012-03-27 3 views
2

정수를 패킹하려고 시도하는 C# 응용 프로그램에서 메서드가 있지만 교대 연산자가 이상하게 작동합니다.
아래 코드의 주석은 줄을 실행 한 후 디버거가 보는 코드 내용을 보여줍니다. 다음 코드에서 비트 연산자의 이상한 동작은 어떻게됩니까?

 long code = 0;   //0x0000000000000000 
     code += (0x1111 << 32); //0x0000000000001111 
     code += (0x2222 << 16); //0x0000000022221111 
     code += (0x3333);  //0x0000000022224444 

내가 0x1111 초래 먼저 실행된다 괄호에 포함 된 코드는 32 비트 왼쪽으로 시프트 될 것으로 기대, 첫 번째 라인을 가지고, 아직은 아니지만, 다음 줄에 시프트가 일어나고 정확한 위치에서도 수행됩니다 (예 : 0x2222는 추가하기 전에 이동해야합니다. 그렇지 않으면 결과는 0x33330000이됩니다).

나는 이것을 설명하는 연산자에 대해 무엇을 놓쳤는가? 당신이 놓친 무엇

+1

변수'code'는 긴 값입니다. 왜 0x1111은 길다라고 생각합니까? –

+0

'0x1111' *은 왼쪽으로 32 시프트되었습니다. 0으로 왼쪽으로 시프트하는 것과 같습니다. – harold

답변

6

은의 int에 그 비트 시프트 작업 0x1111 이후 (32)가 int입니다 모드입니다있는 작업은 0x11110x1111 << 00x1111 << (32 % 32)이다.

원하는 것은 0x1111L << 32입니다. 는 C# 규격의 섹션 7.9에서

:

  • X의 종류 int 또는 uint이며, 시프트 카운트는 하위 count의 5 비트에 의해 주어진다. 즉, 시프트 수는 count & 0x1F에서 계산됩니다.

  • x의 타입이 long 또는 ulong 일 때, 쉬프트 카운트는 count의 하위 6 비트에 의해 주어진다. 바꾸어 말하면, 이동 카운트는 count & 0x3F에서 계산됩니다. 다른 구조가 동일한 INT을 수득 할 때, 0을 생성한다 (32)에 의해 시프트 INT 일부 하드웨어 아키텍처

. 일관된 동작을 가지기 위해 C# 디자이너는 이러한 옵션 중 하나를 선택해야했습니다. 현재의 동작은 단순히 0을 반환하는 아키텍처의 시프트 수에 & 0x1F을 수행하기 만하면됩니다. 그러나 항상 0을 반환하려면 int를 생성하는 아키텍처에서 비교와 분기가 필요합니다. 가지가 비싸기 때문에 대부분의 경우에 가장 빠른 옵션을 선택하는 것이 좋습니다.

+0

그리고 0x1111L로 고칠 수 있습니다. –

+0

@Gabe 감사합니다! 그것이 바로 헨크가 말한 것처럼 오랫동안 선언하거나 하나에 캐스팅하는 것은 예상대로 작동합니다. (큰 * facepalm * 나를 위해!) – sebf

+0

(그리고 어떻게 그리고 왜 카운트가 가려져 있는지에 대한 추가 정보로 업데이트 해 주셔서 감사합니다. – sebf

1

나는 0x1111int으로 처리되기 때문에 믿습니다.