오버 플로우란?
- 오버플로우 : 데이터 유형별 범위를 초과한 값을 할당한 경우 발생
최대값+1
을 하면최소값
이 되는 경우를 의미합니다.
- 언더플로우 : 오버플로우와 반대의 경우
최소값-1
을 하면최대값
이 되는 경우를 의미합니다.
short 타입으로 생성된 256
과 255
를 byte로 캐스팅 하는 경우, 0과 -1값이 나오는데 이런 경우도 오버플로우라고 하고, 두 경우를 자세히 살펴보면 다음과 같습니다.
(short)256 -> (byte)256
1
2
3
0000 0001 0000 0000 -> 2바이트인 short일때는 256이지만
0000 0000 -> 1바이트인 byte로 형변환을 하면 0이 된다.
(short)255 -> (byte)255
1
2
3
0000 0000 1111 1111 -> short일 때는 255
1111 1111 -> byte로 형변환을 했을 때 -1이 된다.
이처럼 큰 범위의 자료형에서 작은 범위의 자료형으로 형변환을 할 때 예상치 못한 값이 나오지 않도록 오버 or 언더플로우를 유의해야 한다.
:pushpin: 2의 보수
위의 설명에서 255(1111 1111)
가 byte 타입에서는 -1
인 이유를 이해하지 못했다.
개인적으로 생각해낸 해답으로는 최소값인 -128
을 이진수로 표현하면 1000 0000
인 점을 이용해서 생각해봤다.
1111 1111
을 다시 표현해보면
1
2
3
4
1111 1111(256)
= 1000 0000(-128) + 0111 1111(127)
= -128 + 127
= -1
그래서 (byte)255
가 -1
이 나오는 것이 아닐까 싶었다.🥲
하지만 위와같은 계산법이 아니라 처음부터 컴퓨터는 2진법에서 음수를 2의 보수로 표현하기 때문이였다.
2의 보수란 양수를 표현하는 2진수에서 0과 1을 뒤집은 다음, +1을 해주는 방법을 뜻하는데
이를 예시로 자세히 살펴보면
1
2
(byte) 1
= 0000 0001
그렇다면 (byte)-1을 2진수로 표현하면?
1
2
3
4
5
1. (byte)1의 2진수 표기법에서 0과 1의 위치를 뒤집는다.
0000 0001 -> 1111 1110
2. +1을 해준다.
1111 1110 -> 1111 1111
이처럼 2의 보수를 통해 8비트에서 -1
을 표현하면 1111 1111
이 된다.
좀 더 자세한 설명은 아레 참고 사이트에 잘 설명되어 있다.
정수형 자동 형변환
short 타입 변수의 최대값에서 1을 더하면 최소값이 나오는 오버플로우 현상을 보기 위해 다음과 같은 예제를 작성했다.
1
2
short shortMax = 32767;
System.out.println(shortMax+1); // 32767
하지만 위 예제처럼 연산을 하면 기대값이였던 -32768이 아닌 32768이 출력된다. short 타입에서 표현할 수 있는 최대값은 32767이기 때문에 32768은 short의 범위를 넘어선 숫자이다.
위와 같은 결과가 나오는 이유는 short 타입의 값에 단순히 1을 더하면 int 타입으로 타입이 자동 변환된다고 한다.
구체적으로 설명하면
- 정수 연산시에 int가 기본 타입이다.
- 게다가 다른 타입을 연산할 때 큰 타입으로 자동 변환된다고 한다.
- 또한 피연산자는 4byte 단위로 계산되어 4byte보다 작은 byte, short, char은 int로 자동 변환된다.
1
2
short shortMax = 32767;
System.out.println((short)(shortMax+1)); // -32768
위 예제처럼 자동 형변환을 제어하기 위해서는 형변환을 직접 명시해야 한다.