C언어 묵시적 형변환 - ceon-eo mugsijeog hyeongbyeonhwan

C언어 묵시적 형변환 - ceon-eo mugsijeog hyeongbyeonhwan

형변환(Type conversion)이란 데이터의 자료형이 바뀌는 것을 의미합니다. 이런 형변환에는 크게 컴파일러에 의해 자동적으로 수행되는 묵시적 형변환이 있고, 프로그래머가 직접적으로 변경하는 명시적 형변환이 있습니다.

묵시적 형변환


묵시적 형변환은 자동적 형변환이라고도 불리는 형변환으로 크게 세 가지가 있습니다.

첫째로 대입 연산시 일어나는 형변환이 있습니다. 저장할 변수의 자료형과 저장될 데이터의 자료형이 다른 경우 일어나는 형변환 입니다. 여기서 저장될 데이터가 저장할 변수의 자료형으로 바뀌는데, 데이터의 크기가 더 작은 경우 올림 변환(promotion), 데이터의 크기가 더 큰 경우 내림 변환(demotion)이 발생합니다.

올림 변환은 크게 문제가 되지 않지만, 내림 변환은 데이터 손실을 일으키므로 사용에 주의해야 합니다.

// promotion
double x;
x = 3; // x에 3.0이 저장됨

// demotion
int y;
y = 3.14; // y에 3이 저장됨

둘째로 정수 연산시 일어나는 형변환이 있습니다. 정수 상태의 데이터(int, short, char 등)를 연산하는 경우 모두 int형으로 통일하여 처리합니다. 이는 CPU가 사용하는 가장 빠른 기억요소인 레지스터(register)와 int형의 크기가 같기 때문에 레지스터 상에서 정수연산을 수행하기 위해 이런 형변환이 일어나는 것입니다.

셋째로 수식에서의 형변환이 있습니다. 계산을 하다보면 서로 다른 데이터가 연산되는 경우가 종종 발생하는데, 이 경우에 피연산자 중 크기가 가장 큰 데이터의 자료형으로 모두 형변환되어 연산이 수행됩니다. 예를 들어 int형 1과 double형 1.5를 더하면 int형 1이 double형 1.0으로 형변환되어 double형 2.5라는 수식값을 갖게 됩니다. 이런 형변환을 이용하면 다음과 같이 몫의 연산을 나누기 연산으로 수행할 수 있습니다.

int x = 5;
double y;

// 수식에서의 형변환으로 정수 데이터(x)의 몫을 계산
y = (1.0 * x) / 2 // 2.5

명시적 형변환


명시적 형변환은 형변환(type cast) 연산자를 이용해 자료형을 직접 바꿔주는 방법입니다.

의 형식으로 사용되며 연산자를 사용한 식이므로 반드시 수식값을 갖게 됩니다.

여기서 주의해야 할 점은 데이터의 자료형 자체가 바뀌는 것이 아니라 데이터를 원하는 자료형으로 수식값을 내놓는다는 것입니다. 예시를 통해 살펴봅시다.

int x = 1;
double y = (int)x;

x // 1
y // 1.0

형변환의 종류는 두가지이다. 묵시적 형변환과 암시적 형변환이 있다. 

생성자가 형변환도 담당하나요?

C언어 묵시적 형변환 - ceon-eo mugsijeog hyeongbyeonhwan
C언어 묵시적 형변환 - ceon-eo mugsijeog hyeongbyeonhwan

i1,i2,i3까지는 납득이 되는 코드이다.

다만 i3=3밑부터 납득이 가지 않는다.

C언어 묵시적 형변환 - ceon-eo mugsijeog hyeongbyeonhwan

출력을 해보면 생성자가 5개나 호출된 것을 확인할 수 있는데

우선 i4부터 보자. int형인 4를 Item으로 형변환을 시켰더니 생성자가 호출되었다. 

이때 이 Item(int num) 생성자를 변환생성자라고 본다.

비슷한 맥락으로 i3=3;을 이해해볼 수 있다. 3이 i3가 될 수 있을까를 고민할때  변환생성자가 있으니 바꿔줄 수 있다!

3을 Item객체로 바꿔주는 과정에서  변환생성자를 통해 임시객체가 생기고, 임시객체에 있는 3이라는 값이

i3로 얕은복사가 된다. (이동 생성자)

그래서 i3=3; 을 묵시적 변환 Item i4=(Item)4;를 명시적변환이라고 한다. 

이제 반대로 Item을 int로 형변환 시켜볼 것이다. 

C언어 묵시적 형변환 - ceon-eo mugsijeog hyeongbyeonhwan

잘 안되는 것을 볼 수 있다. 근데 여기서 엄청난 사실이 있다.

형변환도 연산자다???!!

c언어와 c++에서는 형변환도 연산자다. 이제 오버로딩을 하면된다!

C언어 묵시적 형변환 - ceon-eo mugsijeog hyeongbyeonhwan

여기서 num은 Item클래스의 private 변수로 선언된 num이다. 

C언어 묵시적 형변환 - ceon-eo mugsijeog hyeongbyeonhwan

명시적 형변환은 int로 바뀐다 라고 (int)를 써주며 명시적으로 알려주는 것이고

묵시적 형변환은 굳이 알려주지 않아도 int() operator가 호출된다. 

string으로 형변환 연산자 오버로딩은

num에 해당하는 변수는 string으로 바꾸기 위해서 to_string함수를 이용하고

name은 string이기에 그대로 써준다. 

int itemNum2=i7 처럼 굳이 int로 변환한다고 명시하지 않아도 자동으로 형변환이 일어난다. (int() 연산자 오버로딩을 통해 )

C언어 묵시적 형변환 - ceon-eo mugsijeog hyeongbyeonhwan

연산자 오버로딩 함수 앞에 explicit을 붙여주면서 묵시적 형변환을 막아줄 수 있다. 

int는 4byte, float는 4byte, double은 8byte이다.

1. 형변환은 일시적이기 떄문에 연산 전후의 x, y자체의 형변환이 일어나지는 않았음을 알 수 있다. (메모리크기 그대로)
하지만 연산결과 자체에서는 형변환이 일어난다. (메모리크기 바뀜)

2. double을 int로 바꿀때는, 값이 잘려나간다. 해당 내용은 심각하므로 비주얼스튜디오에서 warning이 나온다.

3. ch=1000이 값이 -24가 나오는 것은, signed char가 char의 기본값인데 앞의 1을 보수 flag로 이해하다보니 값이 음수로 나온 것.

형변환은 위험하다, 큰 것을 작은 데다 욱여넣지 말자!!