Java 언어로 TCP 소켓을 통해 IP 정보를 바이트 배열로 전송하는 로직을 구현하고 있었다. 숫자 167을 바이트 배열에 담아 전송하기 위해서 (byte)167 이렇게 강제 형 변환 과정을 거쳤다. 변환된 값을 출력해서 어떻게 전송되는지 확인해보려고 했는데 -89 라는 값이 표시되었다. 왜 내가 저장한 167이 -89로 출력 되는 것일까? 기초적인 내용이지만 이번 기회에 깔끔하게 정리하고 넘어가기로 했다.

정리하는 과정에서 컴퓨터는 0과 1밖에 모르는 초고속 바보라는 사실을 오랜만에 되새길 수 있었다. 우선 Java에서 int 자료형은 4 byte 자료형이다. int를 byte로 강제 형 변환하면 앞의 3 byte는 제외하고 마지막 1 byte만 살아남는다. 나는 IP 정보를 바이트로 변환하는 중이었고, IP 정보는 0~255 범위의 숫자 4개로 표현되기 때문에 숫자 하나를 단순히 byte 강제 형 변환으로 처리해도 문제되지 않았다.

1 바이트는 8 개의 비트로 이루어지는데, 자바에서 byte는 부호 있는 정수로 표현된다. 그래서 첫 번째 비트는 부호를 나타내며 1이면 음수, 0이면 양수로 인식하고 두 번째 비트부터 여덟 번째 비트가 정수 값을 나타낸다. 즉, 0111 1111 은 127이고, 1111 1111은 -127이다. 그러면 128 이상의 숫자는 저장할 수 없는 걸까?

저장할 수 있다. 저장은 되는데 출력해보면 좀 이상한 값으로 출력 된다. 167은 이진수로 1010 0111이다. 그러면 혹시 -32가 출력 되는 걸까? -(1+2+4+32)

아니다. 이상하게도 -32가 아니라 -89로 출력 된다.

Why? 컴퓨터가 음수를 나타낼 때 2의 보수라는 과정을 거치기 때문이다. 그 과정은 간단하게 외울 수 있다. 첫 번째 비트가 1이면 비트를 반전 시킨 뒤에 1을 더한 값을 표시한다.

  1. 비트 반전 (1의 보수): 1010 0111 → 0101 1000
  2. 1 더하기 (2의 보수): (0101 1000) + 1 = 0101 1001
  3. 십진수 변환: 0101 1001을 십진수로 바꾸면 89다. (1+8+16+64)
  4. 부호 적용: 앞에 -를 붙이면 최종 결과는 -89가 된다.

167은 이진수로 1010 0111이지만 java의 byte 자료형은 이를 음수로 인식하여 2의 보수를 취한 값을 보여주게 되어 -89가 표시되는 것이다.

스스로 경험하며 얻은 깨달음을 공유하기 좋아하며, 세상이 필요로 하는 코드를 작성하기 위해 노력하는 개발자입니다.

답글 남기기

이메일 주소는 공개되지 않습니다. 필수 필드는 *로 표시됩니다