해당 C언어 시리즈는 처음 코딩을 접하는 사람들이 쉽게 이해할 수 있도록 작성되었습니다.
우리는 이전에 자료형에 대해 배웠습니다.
자료형은 크게 정수형과 실수형으로 나뉘고 그 안에서 [ char, short, int ], [ float, double ]로 다시 한번 나뉘게 됩니다.
여기서 눈여겨봐야 할 점은 각 자료형이 할당받는 메모리의 크기와 표현 가능한 데이터의 범위입니다.
일반적으로 메모리의 크기가 크면 더 많은 비트 수를 가지기 때문에 더 넓은 표현 범위를 가집니다. 따라서 정수형과 실수형은 각각 아래의 크기 순서를 갖습니다.
정수형: int(4) > short(2) > char(1)
실수형: double(8) > float(4)
정수형과 실수형 모두 4 바이트 크기를 갖는 자료형을 가지고 있습니다.
그렇다면 정수형과 실수형은 같은 선상에 놓였을 때 누가 우선순위를 가질까요?
정답은 실수형입니다.
같은 메모리 크기를 갖는다고 할지라도 부동소수점 방식에 의해 실수형이 더 넓은 표현 범위를 갖습니다. 그렇기에 아래의 크기 순서로 정리됩니다.
double(8) > float(4) > int(4) > short(2) > char(1)
지금부터 위의 자료형의 크기 순서를 이용하여 형 변환에 대해 배울 겁니다.
형 변환은 기존과 다른 자료형으로 변환하는 걸 의미합니다.
형 변환은 묵시적 형 변환(Implicit type conversion)과 명시적 형 변환(Explicit type conversion)으로 나뉩니다.
묵시적 형 변환은 크기가 작은 자료형과 보다 큰 자료형이 만났을 때 자동으로 일어납니다.
char c_var = 3;
int i_var = 5;
i_var = c_var;
위 코드를 보면 int형 변수 i_var에 char형 변수 c_var의 값을 대입하려는 걸 볼 수 있습니다. int(4)가 char(1)보다 더 크기 때문에 c_var가 int형으로 변환이 되어 i_var에 3이라는 값이 대입이 됩니다.
이때 주의할 점은 대입하는 3번째 줄에서만 값이 일시적으로 int형으로 변환된다는 겁니다.
float f_var;
f_var = 4;
위 코드 역시 마찬가지입니다.
숫자 4는 정수이기 때문에 int형입니다. 하지만 값 대입의 대상이 되는 변수 f_var는 float형입니다. 따라서 숫자 4의 자료형을 int에서 float으로 변환(4 -> 4.0)한 뒤 f_var에 저장하게 됩니다.
묵시적 형 변환은 따로 명시하지 않아도 컴파일러가 자동으로 처리하여 주기 때문에 크게 신경 쓰지 않아도 됩니다.
위에서 묵시적 형 변환은 컴파일러가 자동으로 처리해 준다고 했습니다.
명시적 형 변환은 그와 반대로 코더가 직접 명시를 해줘야만 합니다. 이는 큰 자료형을 보다 작은 자료형으로 변환할 때 사용합니다.
double(8) > float(4) > int(4) > short(2) > char(1)
묵시적 형 변환이 오른쪽에서 왼쪽으로 갔다면, 명시적 형 변환은 왼쪽에서 오른쪽으로 갈 때 사용합니다.
명시를 해야만 하는 이유에 대해 간단한 비유를 들겠습니다.
위와 같이 2칸, 4칸, 1칸의 크기를 가지는 상자가 있습니다. 왼쪽의 상자부터 [ 신발, 가방 ], [ 코트 등의 외투 ], [ 속옷, 양말 ]이 들어있고 공간이 물품과 들어맞는다고 합니다. 그런데 2칸 크기의 상자에 있던 [ 신발, 가방 ]을 버리고 그 공간에 [ 코트 등의 외투 ]를 넣는다고 합니다.
4칸 크기의 상자에 들어맞던 물품을 2칸 크기의 상자에 넣는 건 사실상 불가능한 행위입니다. 물론 [ 코트 등의 외투 ]가 아닌 다른 물품이 있었다면 가능했을 수도 있겠지만요.
이와 같이 큰 크기의 공간에서 작은 크기의 공간으로 이동하게 되면 모든 데이터(물건)을 담지 못하고 흘러넘칠 수 있습니다(데이터 손실). 이러한 이유로 컴파일러는 큰 자료형에서 보다 작은 자료형으로 변환하고자 할 때 오류를 발생시키는 것이지요.
따라서 우리는 실수가 아닌 의도적으로 자료형을 변환했음을 컴파일러에게 알려야 합니다.
캐스팅(Casting)
일반적으로 명시적 형 변환을 캐스팅(Casting)이라 부릅니다.
캐스팅을 하는 방법은 다음과 같습니다.
int i_var = 100;
char c_var = (char) i_var;
위와 같이 형 변환하고자 하는 대상 왼편에 (자료형)을 적어주면 () 안의 자료형으로 값이 바뀌게 됩니다. 위 코드에서는 i_var의 값 100이 char형으로 변환되어 c_var에 들어가게 됩니다.
컴파일러는 정수형은 int, 실수형은 double을 기본으로 연산 처리합니다.
char a = 3;
char b = 5;
char c = a + b;
위 코드를 보면 변수 a와 b 모두 c와 동일한 char 자료형을 가지고 있습니다.
따라서 char형으로 연산이 이루어진 뒤 c에 값이 대입될 것으로 예상됩니다.
하지만 이와 다르게 정수형은 int형으로 연산 처리되기 때문에 변수 a와 b의 값이 모두 int형으로 계산이 되어 8이 되고, 결괏값을 다시 char형으로 변환하여 c에 저장하게 됩니다.
위에서 언급했듯이 실수형은 double형으로 연산이 이루어집니다. 때문에 float 자료형 변수에 실숫값을 대입할 때 컴파일러에게 해당 실숫값은 double형이 아닌 float형으로 처리해야 함을 알려야 합니다.
방법은 간단합니다.
다음과 같이 실숫값 뒤에 f를 붙여주면 됩니다.
float pi = 3.14f;