16.2 자료형의 축소 알아보기
다음과 같이 실수에서 정수로 표현 범위가 좁은 쪽으로 변환하게 되면 값의 손실이 생깁니다.
type_demotion_float_to_int.c
#include <stdio.h> int main() { float num1 = 11.0f; float num2 = 5.0f; int num3 = num1 / num2; // 실수에서 실수를 나누어 2.2가 나왔지만 // 정수 자료형에는 2만 저장되고 0.2는 버려짐 printf("%d\n", num3); // 2 return 0; }
실행 결과
2
11.0에서 5.0을 나누면 2.2가 되어야 하지만 정수 자료형에서는 소수점 이하 자리를 표현할 수 없으므로 2만 저장됩니다. 따라서 0.2가 버려지게 되므로 주의합니다. 이렇게 자료형의 크기가 작은 쪽, 표현 범위가 좁은 쪽으로 변환 되는 것을 형 축소(type demotion)라고 합니다.
형 축소가 일어나면 컴파일할 때 다음과 같이 값의 손실이 일어날 수 있다고 경고가 나옵니다. C 언어에서 자료형을 섞어 쓸 때 이 부분을 항상 주의해야 하며 예상치 못한 버그가 발생하기 쉽습니다.
type_demotion_float_to_int.c(8): warning C4244: '초기화 중': 'float'에서 'int'(으)로 변환하면서 데이터가 손실될 수 있습니다.
컴파일 경고가 나오지 않게 하려면 형 변환(type conversion, type casting, 타입 캐스팅)을 해야 합니다. 보통 형 변환은 자료의 손실을 감안하여 구현하거나, 자료형을 숨기고 싶을 때 등 다양한 방식으로 활용합니다. 이 부분은 'Unit 58 자료형 변환하기'에서 자세히 설명하겠습니다.
이번에는 크기가 다른 정수끼리 연산을 해보겠습니다.
type_demotion_int_to_char.c
#include <stdio.h> int main() { char num1 = 28; int num2 = 1000000002; char num3 = num1 + num2; // char보다 큰 숫자는 저장할 수 없음 // 28 + 2만 남고 앞 자릿수는 버려짐 printf("%d\n", num3); // 30 return 0; }
실행 결과
30
문자 자료형 char도 정수 자료형이므로 int와 함께 연산해도 문제가 없습니다. 하지만 char와 int와 함께 연산한 뒤 char에 저장하면 char보다 큰 숫자는 저장할 수 없습니다. 여기서는 28 + 1000000002에서 28 + 2만 남게 되고 앞 자릿수는 버려집니다.
버려지는 자릿수를 정확하게 표현하기 위해 2진수로 변환했습니다(10진수 단위로 버려지는 것이 아니므로). 이 부분은 지금 당장 이해가 되지 않더라도 걱정할 필요 없습니다. 형 축소가 일어나면 값이 버려질 수 있다는 점만 기억하세요.
지금까지 알아본 형 확장과 축소를 그림으로 나타내면 다음과 같습니다.
오른쪽으로 갈수록 크기가 크고 표현 범위가 넓은 자료형입니다. 그리고 같은 자료형 안에서도 숫자가 높을수록 크기가 큽니다.
1996년 4월 프랑스에서 발사된 아리안 5호 로켓은 발사된 지 37초 만에 폭발하고 말았습니다. 원인은 8바이트(64비트) 실수를 2바이트(16비트) 정수로 변환하는 과정에서 오버플로우가 발생했기 때문인데요. 형 변환 문제로 인해 잘못된 고도가 입력되는 바람에 자동 폭발 장치가 작동되었던 것입니다.
이렇게 형 변환으로 인한 값의 손실 문제는 생각보다 심각한 결과를 초래하기도 합니다. 그러므로 큰 자료형에서 작은 자료형으로 변환은 피하는 것이 좋습니다. 또한, 변환을 하더라도 문제가 발생하지 않는지 반드시 확인해야 합니다.
지금까지 자료형의 확장과 축소를 배웠는데 내용이 다소 어려웠습니다. 지금은 모든 내용을 외울 필요는 없으며 자료형의 축소 때 값이 버려질 수 있다는 점만 기억하면 됩니다.