본문 바로가기

이것저것 알게된 것

char형 연산

백준 1194번 문제에서 char형을 다루면서 생긴 의문이다.

System.out.println('a'-'f');   --> -5

System.out.println('b'-'b');  --> 0

아스키코드 값이 연산 되는 것이라고 짐작은 했지만 정확하게 알고 넘어가기 위해 char연산에 대해 정리한다.


class exam

{

public static void main(String[] args)

{

char a1 = 'a';     //--1

char a2 = a1;    //--2


int i = a1 + 1;                 //--3

char a3 = (char)(a1 + 2);   //--4

a2++;                          //--5


System.out.print( i +" \t" + a2 + "\t" + a3); 

}


결과값

98    b    c


1)  a1에는 문자 'a'의 코드값인 97이 저장된다.

2) a2에는 a1의 값 97이 저장된다. 물론 char타입을 가지고 있기에 자체는 문자 'a'로 인식한다.

3) i에는 97 + 1이 int형태로 저장된다.

char에 들어 있던 a는 int형 97로 변환되고 +1을 하면서 i에는 98이 저장된다.

 이유? int 이하의 변수 타입을 사용하는 경우에는 연산 시 int로 자동변환 된다!

4)  형변환을 해주지 않으면 int타입으로 연산되고, 저장되기 때문에 컴파일시 오류가 난다. 

이유? 3)과 같이 a1 + 2의 연산의 결과는 int타입이 된다. 하지만 담으려는 변수의 타입은 char타입 

따라서 (char)를 붙여 형변환을 먼저 진행하고, (char)형태로 연산을 진행하도록 한다.

그렇게 하면 a1 + 2 를 연산하더라도 아스키코드값 99가 되고 c가 출력된다.

5) 형변환을 해주지 않아도 된다.

이유? 자기자신에 +1을 더하는 것이기 때문에 자연스럽게 char형으로 연산하고, 아스키코드값 98이 저장되고 b가 출력된다.


----> int 이하의 변수타입은 연산 시 int타입으로 자동변환 된다







class exam

{

public static void main(String[] args)

{

char a1 = 'a';

char a2 = a1 + 1;   //컴파일 에러

char a3 = 'a' + 1;


System. out.print(a3);

}


위의 코드를 실행하면 int보다 작은 형태의 변수는 int형으로 변환되는 것이 맞지만,

a2는 컴파일에러가 발생하고 a3는 에러가 발생하지 않는다.

이유는? 'a' + 1은 리터럴 간의 연산이기 때문


리터럴이란? 

변수를 선언할 때 사용하는 수 'a', 10등과 같이 변수,상수들을 초기화 할 때 적는 값들을 말한다.


위에서 'a'는 변수 a1을 초기화 할때 사용한 값이다.

변수가 아닌 상수 또는 리터럴간의 연산은 프로그램 실행 중 변하는 값이 아니기 때문에,

소스코드를 컴파일 시 컴파일러가 먼저 계산하고 리터럴간의 연산을 실행한다.

컴파일 전 

컴파일  후

 char c = 'a' + 1;

 char c = 'b';

 int i = 100 * 100

 int i = 10000;

이처럼 'a' + 1; 과 같은 연산은 리터럴간의 연산으로 컴파일러는 연산을 미리 실행하여 char c = 'b'로 나타내게 된다.

int i = 100*100 도 100이 리터럴(숫자)이므로 컴파일러는 리터럴간의 연산을 먼저 실행하여 int i= 10000; 라고 나타낸다.


만약 수식에 변수가 들어가 있는 경우에는 프로그램 사용 도중 값이 변할 수도 있기 때문에 컴파일러가 미리 계산을 할 수 없다.

그래서 형변환이 필요하고, 형변환을 하지 않을 경우 오류가 생기게 된다.


다시 정리하자면

char i = 'a'

char ch = i + 1; --> 컴파일 에러 

char exam = 'a' + 1;  --> 컴파일 에러 안남

i + 1연산 시,

 i는 char타입의 "변수"이므로 컴파일러는 미리 계산할 수 없다.(변수는 도중 값이 변할 수 있으므로)

"char타입 + int타입"의 연산이 실행

int보다 작은 형태의 변수는 int로 변환된다에 맞춰  i는 int값으로 자동 변환되어 연산된다. --> 결과는 int형

그러나 결과값을 담을 변수의 타입이 char이다. 따라서 컴파일 오류

(char)( i + 1); 로 형변환을 통해서 int형의 결과값을 char형으로 변환한다.


'a' + 1연산 시, 

'a'는 변수가 아닌 "문자리터럴"이므로 컴파일러는 소스 컴파일 시에 미리 연산을 실행한다.

컴파일러가 실행한 연산의 결과 값은 'b'가 되고,

char c = 'b'가 실행된다.  



리터럴과 상수에 대해서 더 자세히 알아본다.

String name = "gangdong";

int i = 100;

name, i 는 변수이며, 이러한 변수들은 연산 도중 언제든지 변할 수 있다.

반면 

"gangdong"은 문자열 리터럴이고, 100은 숫자형 리터럴이다.


그리고 상수란 변수와 같이 초기화를 하지만 초기화 이후에는 더이상 변할 수 없는 값을 말한다.

final String name = "gangdong";

final int i = 100;

위와 같이 상수를 선언하면 변수와는 달리 i=26과 같이 값을 재할당 해줄 수 없다.

값을 바꾸려고 해도 컴파일 시 에러가 발생한다.


이러한 연산자의 성질을 이용해서 소수점 몇자리를 버리는 연산도 가능하다.

calss exam

{

public static void main(String[] arsg)

{

float pi = 3.141592f;

float shortpi = (int)(pi * 100 ) / 100f;

System.out.print(shortpi);

}

}


결과 값

3.14


int형 변수 타입이 소수점 아래의 모든 숫자를 버리는 성질을 이용


pi * 100의 연산결과는 314.1592인데, (int)로 형변환을 했기 때문에 소수점 아래 자리를 모두 버리게 된다.

그러므로 연산 값은 314만 남게 되는데, 그 후 100f로 나눠줬기 때문에 3.14로 값을 저장하게 된다.







'이것저것 알게된 것' 카테고리의 다른 글

Java EOF 처리  (0) 2019.08.03
2차원배열 특정값으로 채우기  (0) 2019.08.02
비트연산자  (0) 2019.07.20
필드와 변수의 차이,선언위치,초기화  (0) 2019.07.16
Scanner와 BufferedReader  (0) 2019.06.19