백준 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 |