글
비트 시프트 연산자란 말그대로 bit 를 shift 시켜주는 녀석이다.
연산자는 다음과 같이 3가지가 있다.
(1) << : 왼쪽으로 이동
(2) >> : 오른쪽으로 이동
(3) >>> : unsigned, 오른쪽으로 이동
좀 더 쉽게 이해해보자.
'A << B' 라는 수식이 있다고 하면, A 라는 녀석의 비트 값을 B 만큼 왼쪽으로 이동시키겠다.
라고 이해하면 된다. (단, A와 B는 정수이다)
이제 하나씩 알아보자.
(1) << 연산자
int a = 0x00000010; // 10진수 '16' 을 16진수로 표현
a = a << 2;
연산 前, a = 0000 0000 0000 0000 0000 0000 0001 0000 // 16
연산 後, a = 0000 0000 0000 0000 0000 0000 0100 0000 // 64
색상으로 표시된 부분에 주목하자.
비트 연산을 할 때는 비트가 rotation 되는 게 아니라
왼쪽 끝부분이 그냥 잘리고 없어진다. C언어도 마찬가지이다.
음수의 경우도 살펴보겠다.
(참고로 int 는 32 비트지만 맨 앞의 비트는 부호 역할을 하므로 - 양수는 0, 음수는 1 -
최소값은 -2^31, 최대값은 2^31-1 이다)
a = -2147483648 // -2^31
a <<= 1;
연산 前, a = 1000 0000 0000 0000 0000 0000 0000 0000 // -2147483648 = -2^31
연산 後, a = 0000 0000 0000 0000 0000 0000 0000 0000 // 0
<< 연산자를 정리하자면,
비트 값들을 왼쪽으로 이동시킨 후에 오른쪽의 빈 공간에는 모두 0 으로 채운다.
(2) >> 연산자
int a = 2147483647; // 2^31-1
a >>= 1;
연산 前, a = 0111 1111 1111 1111 1111 1111 1111 1111 // 2147483647 = 2^31-1
연산 後, a = 0011 1111 1111 1111 1111 1111 1111 1111 // 1073741823 = 2^30-1
이번엔 오른쪽 끝부분이 잘리고 없어진다.
하지만 << 연산자와 똑같다고 생각하면 오산이다.
음수의 경우를 살펴보겠다.
a = -2147483648 // -2^31
a >>= 1;
a >>= 30;
연산 前, a = 1000 0000 0000 0000 0000 0000 0000 0000 // -2147483648 = -2^31
연산 中, a = 1100 0000 0000 0000 0000 0000 0000 0000 // -1073741824 = -2^30
연산 後, a = 1111 1111 1111 1111 1111 1111 1111 1111 // -1 = -2^0
양수와 음수의 >> 연산 결과가 다르다는 것을 눈치챘을 것이다.
>>연산자를 정리하자면,
비트 값들을 오른쪽으로 이동시킨 후에 왼쪽의 빈 공간에는
양수는 모두 0 으로,
음수는 모두 1 로 채운다.
(3) >>> 연산자
a = -2147483648 // -2^31
a >>>= 1;
a >>>= 30;
연산 前, a = 1000 0000 0000 0000 0000 0000 0000 0000 // -2147483648 = -2^31
연산 中, a = 0100 0000 0000 0000 0000 0000 0000 0000 // 1073741824 = 2^30
연산 後, a = 0000 0000 0000 0000 0000 0000 0000 0001 // 1 = 2^0
>>> 연산자는 부호를 신경쓰지 않는다.
그러므로 정리하자면,
비트 값들을 오른쪽으로 이동시킨 후에 왼쪽의 빈 공간은 모두 0 으로 채운다.
* 주의점 *
1. 연산 가능한 타입이 byte, short, int, long 타입과 char 타입이 있는데..
int 보다 작은 비트의 타입 byte, short, char 는 int 로 변환되서 Shift 가 된다고 한다.
그래서 결과값을 int 로 받지 않고 기존의 타입 그대로 받으면 문제가 발생하게 된다.
byte b = -1;
b = b >>> 2; // error
b = (byte) b >>> 2; // non-error but...
연산 前, b = 1111 1111 1111 1111 1111 1111 1111 1111; // -1
연산 中, b = 0011 1111 1111 1111 1111 1111 1111 1111; // 1073741823 = 2^30-1
연산 後, b = 1111 1111; // -1, 위 결과의 오른쪽으로부터 8 bit 만 끊어서 캐스팅.
-1 값을 갖는 byte 변수에 >>> 연산을 했는데... 음수가 나오는 결과가 나오게 된다.
2. 비트 연산자의 피연산자 ( A << B 에서 B에 해당하는 부분 ) 그대로의 값으로
시프트 하는 것이 아니라 나머지 연산(%)의 결과값으로 시프트를 한다.
이해가 잘 안되니 예제를 보자.
int c = -1;
c = c >>> 32;
c 의 결과값은 32 % 32 = 0 이므로 아무런 시프트가 되지 않은 값, 똑같이 -1 을 갖는다.
byte 타입이라면 % 8, short 타입이라면 % 16, long 타입이라면 % 64 의 결과값으로 시프트 된다.
(출처 : 자바의神 Vol.1 , http://blog.naver.com/salagswk/150046360210,
http://docs.oracle.com/javase/tutorial/java/nutsandbolts/op3.html)
'Programming > Java' 카테고리의 다른 글
자바의神 Vol.1 : Garbage Collector 은 어떻게 진행될까? (0) | 2014.05.26 |
---|---|
자바의神 Vol.1 : Annotation (0) | 2014.05.24 |
자바의神 Vol.1 : Nested Class (0) | 2014.05.22 |
자바의神 Vol.1 : 접근 제어자, Overriding과 Overloading (0) | 2014.05.21 |
RECENT COMMENT