Java - Operators, TypeConversion, and MemoryOverflow


1. 연산자

  • 연산자는 말 그대로 자료형 타입에 수학적 논리적 연산을 사용하는 기호들을 말한다.
    • ++, – 와 같은 증감 연산자
    • =, +=, -=, /= 등과 같은 대입 연산자
    • +, -, /, %, * 과 같은 산술 연산자
    • ==, !=, >= 와 같은 비교 연산자
    • &&, ㅣㅣ 와 같은 논리 연산자
    • &, ㅣ 와 같은 비트 연산자
    • «, » 와 같은 시프트 연산자들이 있다.



2. 자료형에서 연산자를 사용할 때 특이한 특징

  • 정수형과 정수형을 연산하면 int로 자동 캐스팅
  • 정수형과 소수형을 연산하면 double로 자동 캐스팅
  • 소수와 소수형을 연산하면 double로 자동 캐스팅
  • char와 int 사이에 연산식이 들어가도 int로 자동 캐스팅
    • 단 여기서 주의해야 할 점은, char에 담긴 숫자는 ASCII 코드로 들어가기 때문에, 명확한 숫자로 바꾸려면 -48을 해줘야 한다.
    • 아래는 char와 int의 예시코드이다.
        public class test {
        public static void main(String[] args) {
            char a = '1';
            char b = '2';
            int c = a + b;
            int y = a;
            int z = b;
            System.out.println(c); // 99
            System.out.println(y); // 49
            System.out.println(z); // 50
      
      
            int d = 1;
            char e = (char) d;
            int f = e;
            System.out.println(e); // ASCII 에서 1에 해당하는 제어 문자 SOH가 들어감.
            System.out.println(f); // 1
        }
        }
      
    • 처음부터 char 형에 ‘1’, ‘2’로 들어가 있는걸 int로 바꾸거나 연산을 해주면 ASCII 코드로 변환되어 49, 50이 반환된다. 그래서 -48을 해줘야지만 원래 숫자가 나온다.
    • 그러나 원래 int에 담겨있건걸, char로 넘기면 그 숫자 그대로가 ASCII코드가 넘어가므로, 1을 넘기면 ASCII 코드 1이 된다. 그래서 제어 문자 SOH라는게 들어가고, 다시 int로 넘겼으므로 1이 출력된다.


  • 다음은 정수형 자료 예시코드이다.
      byte b1 = 5;
      byte b2 = 10;
      byte b3 = (byte) (b1 + b2);
    
    • 해당 코드를 보면, byte와 byte를 더했음에도 byte가 되려면 (byte)라는 캐스팅타입을 입력해야 한다.
    • 이 이유는 연산식 때문에 강제로 int가 되었기 때문이다.
    • 또한 long 같은 경우에는 int보다 범위가 크므로, long + long을 해서 long에 넣어도 캐스팅하지 않아도 된다.



3. 형변환의 2가지 종류

  • 자동타입변환과, 강제타입변환(Casting)이다. 자동타입변환은 묵시적이며, 강제타입변환은 명시적이다. 자동타입변환
    • 자동 타입변환은 프로그램이 자동으로 형변환을 해주는 것을 말한다. 이는 작은크기의 자료형에서 큰크기의 자료형으로 형변환을 시도할 때 이루어진다.
    • 참고로 byte -> short -> int -> long -> float -> double 순서로 본다.
      • float와 double은 int와 long처럼 4바이트, 8바이트의 메모리를 먹기때문에 의아할 수 있으나, 정수보다 표현 범위가 더 크기 때문에 큰 타입으로 본다.
    • 그리고, char -> int로 변환시에도 자동 형변환이 이루어지는데, 해당 문자의 아스키코드로 저장이 된다. ‘A’는 65로 저장되는 것이다.
      • 반대로 int에서 char로 바꾸려면 Casting을 해줘야 한다. 음수가 들어갈 수 있기 때문이다. 강제타입변환
    • 강제 타입변환은 char c = (char) i; 이렇게 앞에 캐스팅 타입을 명시적으로 붙여줌으로써 타입을 변환하는 방식이다.
    • 자동타입변환과는 반대로 큰 크기에서 작은 크기의 자료형으로 변환할 때 사용한다. 이는 작은 크기에서 담을 수 없는 값을 큰 크기에서 줄 수 있기 때문에 그 점을 감안하고서라도 변환할 것인지에 대해 명시적으로 표현한 것이다.
    • 단, 이럴 경우 메모리 오버플로우나 메모리 언더플로우 현상으로 인해 원하지 않는 값이 나올 수 있다.



4. 메모리 오버플로우와 메모리 언더플로우

  • 메모리는 정해져있다.
  • 이를테면 byte는 8비트의 메모리와 -128 ~ 127 까지의 범위를 가지고 있다.
  • 이건 -2^7 ~ 2^7 의 범위를 가지고 있다고 할 수 있다.
    • 왜 8비트의 메모리를 가지고 있는데 2의 7승까지만 계산을 할까.
    • 그 이유는 맨 앞의 비트는 양수와 음수를 판별하는 비트이기 때문이다.
    • 0이면 양수, 1이면 음수인 셈이다.
    • 그래서 1 0 0 0 0 0 0 0 ~ 0 1 1 1 1 1 1 1 이 범위인 셈이다.
      • 음수는 2의 보수를 따른다.


  • 0 1 1 1 1 1 1 1 이면 127로 byte의 가장 마지막 양수이다.
  • 여기서 ++ 을 해준다면 어떤 값이 나올까?
  • -128이 나온다.
  • 어떻게 이렇게 된 것일까?
    • 메모리는 순환된다고 보면 편한다.
    • 최대값과 최소값 붙어있는 개념이다.
    • 127인 0 1 1 1 1 1 1 1 에서 1이 추가되어 1 0 0 0 0 0 0 0 이 된 것이고, 이는 음수로 되기에 -128이 된다.
    • 반대로 -128에서 –;를 해주면 127이 된다. ( 이 것이 메모리 언더플로우이다. )
  • 그럼 우리가 -127을 이진수로 어떻게 표현해 줄 수 있는지도 궁금할 것이다.
    • 결론부터 말하면 1 0 0 0 0 0 0 1 이다.
    • 그 이유는 2의 보수를 사용한 것인데, 127인 0 1 1 1 1 1 1 1 을 반전시켜서 1 0 0 0 0 0 0 0 을 만든 후 1을 더한 값이다.
  • 2의 보수는 우리가 C언어에서 ^를 활용해서 많이 뒤집는데, 음수면 비트를 뒤집은 후에 1을 빼주면되고, 양수면 비트를 뒤집은 후에 1을 더해주면 된다.
  • 그래서 8비트를 가지고 있음에도, 1 0 0 0 0 0 0 1 이 129가 되는 것이 아니라 -127이 되는 것이다.
  • 이는 byte 뿐 아니라, 모든 정수형 타입 자료형에서 통용된다.






results matching ""

    No results matching ""