저번 강의를 이어서 이번에는 '형 변환'에 대해 배워보겠습니다.
char형이나 int형으로 선언된 변수를 double형으로 바꿀수는 없을까요? 가능합니다.
그리고 이것이 자료형의 변환입니다.
자료형 변환은 다음과 같이 크게 두 종류로 나뉩니다.
-자동 형 변환(묵시적 형 변환)
-강제 형 변환(명시적 형 변환)
말 그대로 자동 형 변환은 자동으로 형 변환이 이루어 지는 것이고, 강제 형 변환은 강제로 형 변환이 이루어 지는 것을 말합니다.
자동 형 변환은 대입연산에 의해 발생하는 형 변환과, 정수의 승격에 의한 형 변환, 마지막으로 피연산자의 자료형 불일치로 인한 형 변환이 있습니다.
먼저 대입연산에 의해 발생하는 형 변환부터 봅시다.
대입 연산자는 왼쪽과 오른쪽에 존재하는 두 피연산자의 자료형이 일치하지 않으면, 왼쪽에있는 피연산자를 대상으로 형 변환이 자동으로 일어납니다. 무슨 소린지 잘 모르시겠죠? 다음 코드를 봅시다.
다음 경우에는 어떻게 될까요?
우리는 전에 char형은 -128 ~ +127까지의 수를 표현할 수 있다는 것을 배웠습니다.
그런데 위 코드에서는 char형 변수 ch에 130을 대입하고 있죠. 그럼 어떻게 될까요?
130가 저장된 num의 비트열은 00000000 00000000 00000000 10000010 입니다.
이를 char형의 크기인 1바이트로 줄여야 합니다. 그렇게 되면 '상위 바이트의 손실'이 발생하며, 다음과 같이 됩니다.
10000010 //정수로 -126
이렇게 상위 바이트 손실로 MSB까지 바뀌어 부호가 바뀌는 경우도 있습니다.
위 경우를 정리하겠습니다.
정수를 실수로 형 변환하는 경우
-정수 데이터를 실수로 표현하게 되는데 실수의 표현범위가 정수에 비해 훨씬 넓으므로 데이터 손실은 일어나지 않는다.
하지만 실수이기 때문에 오차는 존재한다.
실수를 정수로 형 변환하는 경우
-정수는 소수점 이하의 값을 표현하지 못하기 때문에, 소수점 이하 값은 버려진다.
바이트 크기가 큰 정수를 바이트 크기가 작은 정수로 형 변환하는 경우
-변환하고자 하는 정수의 바이트 크기에 맞게 상위 바이트를 소멸시킨다. 이로 인해 부호까지 바뀔 수 있으니,
주의가 필요하다.
지금까지 설명한 내용을 예제로 확인해봅시다.
실행결과
이번에는 정수의 승격에 의한 자동 형 변환에 대해 알아봅시다.
우리는 일반적으로 CPU가 처리하기에 가장 적합한 크기의 정수 자료형을 int로 정의해서 int형 연산의 속도가 다른 자료형의 연산속도와 같거나 더 빠르다고 했습니다.
따라서 int보다 작은 크기의 정수형 데이터는 int형으로 형 변환 되어서 연산이 진행된다고 했습니다.
다음과 같은 경우에도 int형으로 형 변환이 발생합니다.
이러한 형태의 형 변환을 '정수의 승격(Integral Promotion)'이라 합니다. 그런데 위 코드에서 정수의 승격만 일어난 것이 아닙니다. num1+num2의 계산결과는 4바이트 크기의 int형이므로 num3에 저장할 때도 앞서 본 대입연산에 의한 형 변환이 다시 일어나게 됩니다.
자 여기서 궁금증을 하나 풀고 갑시다.
정말로 int형이 다른 자료형에 비해 연산이 더 빠를까요?
옛날에는 CPU종류가 16비트 CPU 32비트 CPU밖에 없었습니다.
16비트는 2바이트 32비트는 4바이트. 즉 int형으로 연산을 진행하면 데이터 변환이 필요가 없어져서 더 빠르게 연산이 진행되는 것이죠.
하지만 지금은 64비트 시스템이 등장하면서 이제는 자료형에 따른 연산속도는 의미가 없어집니다.
요즘 나오는 CPU는 옛날과 구조도 다르고 속도도 매우 빠릅니다. 어떤 자료형으로 연산하든 속도차이가 거~~~의 없죠.
하지만 먼 훗날 새로운 CPU의 탄생도 고려해야 하기 때문에 C언어의 '정수의 승격'은 여전히 의미를 갖습니다.
다음은 제 블로그 C언어 강의 09챕터에 달린 댓글입니다.
아직 이해가 힘드실 수 있습니다. 그러니 이해가 힘드시다면 그냥 참고만 하고 넘어가셔도 좋습니다.
다음으로 피연산자의 자료형 불일치로 인한 자동 형 변환에 대해 알아보겠습니다.
사칙연산을 진행할 때에는 두 피연산자가 필요합니다.
이 때 이 둘의 자료형은 일치해야 하며, 일치하지 않을 시 자동으로 형 변환이 일어납니다.
다음 문장을 봅시다.
위 문장에서는 실수형 데이터 4.44와 정수형 데이터 20의 합을 요구하고 있습니다.
그런데 이 둘은 데이터 표현방식이 다르므로 사실 덧셈이 불가능 합니다.
CPU는 같은 자료형의 두 피연산자를 대상으로만 연산이 가능하도록 설계되어 있기 때문입니다.
따라서 위 문장은 4.44를 정수로 바꾸거나 20을 실수로 바꾸어야 합니다.
어떤 것을 바꾸는 것이 좋은 선택일까요?
4.44를 정수로 바꾸면 4가 되고 20을 실수로 바꾸면 20.0이 됩니다.
즉, 데이터의 손실을 최소화 하려면 정수형 데이터를 실수로 바꿔야 합니다.
실제로도 이렇게 int형 정수를 double형 실수로 형 변환이 이루어집니다.
이렇듯 피연산자의 자료형이 일치하지 않아서 발생하는 자동 형 변환은 데이터의 손실을 최소화 하는 방향으로 진행됩니다.
여기서 말하는 데이터 손실 최소화 기준은 다음과 같습니다.
위 그림의 화살표 방향은 형 변환에서의 상대적 우선순위를 나타냅니다. 예를 들어 int형 정수와 long형 수를 대상으로 덧셈연산을 하는 경우, 화살표의 방향에 따라서 int형 정수가 long형 정수로 자동 형 변환이 됩니다. 또 double형 실수와 long형 정수를 대상으로 덧셈연산을 하면 long형 정수가 double형 실수로 형 변환됩니다.
그런데 위 그림에는 왜 char와 short가 없을까요?
char형 정수와 short형 정수의 덧셈연산 과정을 생각해봅시다.
char형은 1바이트이고 short형은 2바이트이므로 short형으로 자동 형 변환 될까요? 아닙니다!
이 경우 '정수의 승격'에 의해서 둘 다 int형으로 형 변환됩니다. 그래서 위 그림에는 char와 short는 생략된 것입니다.
그리고 long long은 8바이트이고 float는 4바이트 인데 어째서 우선순위가 앞서있는 것일까요?
바이트 크기를 기준으로 우선순위를 정했다면 long long이 더 앞섰을 것입니다.
하지만 기준은 '데이터 손실의 최소화'이므로 실수형인 float가 더 앞서는 것입니다.
비록 오차는 존재하지만 값의 표현 범위는 float가 더 넓기 때문입니다. 반대의 경우에는 '소수점 부분의 손실'이 발생하기 때문에 거의 무조건 손실이 발생한다고 봐야합니다. 그래서 형 변환의 우선순위는 정수 자료형보다 실수 자료형이 무조건 앞서는 형태로 정의 되어있습니다.
마지막으로 명시적 형 변환에 대해 알아봅시다.
명시적 형 변환은 형 변환 연산자를 이용해서 강제로 형 변환을 하는 것을 말합니다. 예제 봅시다.
실행결과
0.5가 출력될 줄 알았으나 결과로 0이 출력되었습니다. 정수 1과 2의 나눗셈 결과는 0이니 이 값이 double형으로 자동 형 변환 되어 변수 result에 저장된 것입니다. 그럼 위 코드 9행을 다음과 같이 변경해봅시다.
C언어에서 소괄호는 연산의 순서를 지정하는 수학적 의미로도 쓰이지만 이렇게 자료형을 변경할 때도 사용됩니다.
위 문장에서 사용된 소괄호를 가리켜 '형 변환 연산자'라고 합니다.
그럼 이 연산 과정을 봅시다.
위 문장은 다음과 같은 형태가 됩니다.
여기서 num2도 왼쪽 피연산자에 의해 double형으로 변환 됩니다.
그리고 마지막으로 나눗셈이 진행되고 그 결과가 변수 result에 저장됩니다.
다음과 같은 경우에는
명시적으로 형 변환을 해주는 것이 코드 분석에 도움을 주기 때문에 형 변환 연산자를 사용하는 것이 좋습니다.
물론 이런 상황에서 명시적으로 형 변환을 한다해도 달라지는 것은 없습니다.
이번 강의는 여기서 마치도록 하겠습니다.
다음 강의는 printf와 scanf함수에 대한 추가적인 이야기에 대해 다룹니다.
다음 강의 때 뵙겠습니다.
'C언어 강의' 카테고리의 다른 글
(C언어 강의) Chapter -12 반복명령을 위한 키워드(while) (0) | 2016.07.28 |
---|---|
(C언어 강의) Chapter -11 printf와 scanf함수에 대한 추가적인 이야기 (0) | 2016.07.26 |
(C언어 강의) Chapter -10 상수와 형 변환 -01 (0) | 2016.07.24 |
(C언어 강의) Chapter -09 여러가지 자료형 (3) | 2016.07.08 |
(C언어 강의) Chapter -08 비트 연산자 (2) | 2016.07.06 |