2011-03-05 3 views
3

다음 프로그램과 예기치 않은 방식으로 작동합니다. 루프 조건이 false를 반환하고 종료하고이 프로그램을 실행 한 경우는 32Java 기괴한 프로그램 출력의 시프트 연산자

를 인쇄해야합니다 동안 32에 도달하면 우리가이 프로그램의 출력에 대해 생각하는 경우

public class ShiftProgram 
{ 
     public static void main(String[] args) 
     { 
      int i = 0; 
      while(-1 << i != 0) 
        i++; 
      System.out.println(i); 
     } 
} 

, 그것은 아무것도 인쇄하지만 이동하지 않습니다 무한 루프로. 어떤 아이디어가 계속되고 있니? 미리 감사드립니다. 시프트 카운트가 해석

답변

6

무엇이 잘못되었는지 보려면 루프에 (-1 << i)을 인쇄 해 보셨습니까? 당신이 할 경우, 당신은가는 것을 볼 수 있습니다 :

-1 << 0 = -1 
-1 << 1 = -2 
-1 << 2 = -4 
-1 << 3 = -8 
-1 << 4 = -16 
-1 << 5 = -32 
-1 << 6 = -64 
-1 << 7 = -128 
-1 << 8 = -256 
-1 << 9 = -512 
-1 << 10 = -1024 
-1 << 11 = -2048 
-1 << 12 = -4096 
-1 << 13 = -8192 
-1 << 14 = -16384 
-1 << 15 = -32768 
-1 << 16 = -65536 
-1 << 17 = -131072 
-1 << 18 = -262144 
-1 << 19 = -524288 
-1 << 20 = -1048576 
-1 << 21 = -2097152 
-1 << 22 = -4194304 
-1 << 23 = -8388608 
-1 << 24 = -16777216 
-1 << 25 = -33554432 
-1 << 26 = -67108864 
-1 << 27 = -134217728 
-1 << 28 = -268435456 
-1 << 29 = -536870912 
-1 << 30 = -1073741824 
-1 << 31 = -2147483648 
-1 << 32 = -1 
-1 << 33 = -2 
-1 << 34 = -4 
-1 << 35 = -8 
-1 << 36 = -16 
[.. etc ..] 

language specification에 따르면

N < <의의 값은 N의 왼쪽 이동 비트 위치를; 이는 전력에 2를 곱하는 것과 동일합니다 (오버 플로우가 발생하더라도).

... 결과는 항상 음수로 유지됩니다.

그 문서도 있음을 알려줍니다 : 왼쪽 피연산자의 승진 타입이 INT 인 경우

이, 오른쪽 피연산자의 다섯 최하위 비트 시프트 거리로 사용됩니다. 이는 오른쪽 피연산자가 마스크 값 0x1f를 갖는 비트 논리 AND 연산자 & (15.22.1)에 적용되는 것과 같습니다. 따라서 실제 사용되는 이동 거리는 항상 0에서 31까지의 범위입니다.

그래서 당신은 32의 변화를 사용하는 경우, 그 0입니다 32 & 0x1f의 변화로 해석합니다. 은 0이 아니라 -1인데, 0이 아닙니다.

6

int (32)의 비트 수를 모듈로 등 i << 32 단지 i이다 i << 0이다. 따라서, 당신은 결코 0을 얻지 못할 것입니다. 내 소스는 http://www.janeg.ca/scjp/oper/shift.html입니다. int n = -1; while (n != 0) {i++; n <<= 1;}과 같은 작업을 수행하면 원하는대로 결국 0에 도달합니다.

관련 문제