카테고리 없음

형변환에 대하여

W001N 2023. 6. 4. 22:48

 

 

1. 형변환은 왜 일어날까 ? 

 

 

상식적으로 우리는 2 + 1.625 = 3.625 라고 생각합니다. 

그러나 0 과 1 밖에 모르는 컴퓨터 입장에서는 둘을 그냥 더한다면 예상치 못한 값이 나오게 됩니다. 

 

보통 정수를 int 에 저장한다면 2 의보수법 ,

실수를 float 에 저장한다면 IEEE 754 표준의 부동소수점 변환을 이용합니다. 

 

 

 

 

둘을 더한다면 11 이 나오게 됩니다. 

 

우리의 상식과 생각보다 많이 멍청한 컴퓨터를 연결할 필요가 있는데 

그 작업을 컴파일러 라는 프로그램이 형변환으로 담당해줍니다. 

 

컴퓨터 입장에서는 자기가 멍청하다는 것을 들키지 않기 위해 형이 같은 경우만 연산합니다. 

 

보통 형변환은 우리가 모르게 컴파일러가 암묵적으로 해주기 때문에 어떤 경우에 형변환이 일어나는 지

파악하는 것은 중요합니다. 

 

 

2. 형변환이 일어나는 경우 (1) 보통의 산술 변환 

 

 

보통의 산술 변환 ( Usual arithmetic conversions ) 은 산술 이나 비교를 포함한 대부분의 이항 연산자에서 정수형 또는 실수형인 두 피연산자에 대하여 적용됩니다. 

규칙은 두 피연산자의 형에 따라 다른데 다음과 같습니다. 

 

< 앞의 절차가 충족될 경우 뒤의 절차는 시행하지 않습니다. >

피연산자 A , B 가 있을 때 

1) A , B 중 하나의 type 이 long double 일 경우 이에 맞춰 형변환 한다. 

2) A , B 중 하나의 type 이 double 일 경우 이에 맞춰 형변환 한다. 

3) A , B 중 하나의 type 이 float 일 경우 이에 맞춰 형변환 한다. 

 

 

 

 

1 ~ 3 을 충족하지 않았다면 둘다 정수형 인게 확실한 상황입니다. 

이때 위의 랭크 표에서 A , B 중 4 ~ 6 가 있을 경우 일단 3으로 정수의 승격 ( integer promotions ) 합니다.

 

4) A , B 의 type 이 같을 경우 형변환 하지 않습니다. 

5) A , B 둘다 unsigned 이거나 둘다 signed 일 경우 낮은 랭크가 높은 랭크에 맞춰 형변환 합니다. 

6) unsigned 의 랭크가 signed 의 랭크보다 높거나 같다면 signed 를 unsigned 에 맞춥니다. 

7) signed 피연산자가 모든 unsigned 피연산자의 표현 범위를 포함한다면 unsigned 를 signed 에 맞춥니다. 

8) 둘다 signed 의 랭크에 해당하는 unsigned 에 맞춥니다. 

( 예를들어 (int , unsigned short int) 라면 , 랭크 3 의 unsigned int 에 맞춥니다. )  

 

위의 복잡한 과정을 3줄 요약하면 다음과 같습니다. 

 

1. 데이터의 손실을 최소화하기 위해 보통 정수형을 실수형에 맞춘다. ( float + int --> float + float )

2. 바이트의 손실을 최소화하기 위해 보통 작은 바이트를 큰 바이트에 맞춘다. ( long + int --> long + long )  

3. unsigned 와 signed 사이의 연산은 웬만하면 하지 않는게 좋다. 

 

 

3. 형변환이 일어나는 경우 (2) 할당 , 함수

 

 

다음의 경우에도 형변환이 일어납니다. 

 

1. 할당 연산자에서 두 피연산자의 형이 일치하지 않음.  

2. 함수에서 return 문과 return type 의 형이 일치하지 않음. 

3. 함수 인자와 매개변수의 형이 일치하지 않음. 

 

위의 경우 

1 은 왼쪽 피연산자 , 2 는 return type , 3 은 함수 인자에 맞춰

1 의 오른쪽 피연산자 , 2 의 return 문 type , 3 의 함수 매개변수가 형변환 합니다. 

 

 

#include <stdio.h> 

int main( ){

	int a = 0 ; 
    	float b = 3.14 ; 
    
    	a = b ; // a 에 3 이 할당
    	printf("%d" , a) ; // 3 출력 
    
    	return 0 ;
    
}

 

 

이때 , 2 가지 문제가 발생할 수 있습니다.

 

첫째로 실수형을 정수형에 맞춰 형변환할 경우 소수부분이 손실될 수 있습니다. 

위의 코드에서 a 에는 3 이 저장됩니다. 

형변환에 의해 0.14 가 손실된 것입니다. 

 

두번째로 변환하는 데이터가 변환받는 형의 범위를 벗어날 경우 의미 없는 값을 전달받을 수 있습니다. 

 

 

#include <stdio.h>

int main( ) {
	
    	int a = -3;
    	unsigned int b = 0 ; 
        
        b = a ; // 의미없는 값 할당 
        printf("%u" , b) ; // -3 출력 하지 않음 
        
        return 0 ;
   }

 

 

unsigned int 의 범위는 ( 0 ~ 4,294,967,295 ) 이기에 의미없는 값을 전달 받습니다. 

 

 

4. 형변환 연산자 cast

 

 

컴파일러가 자동으로 형변환을 해주지만 때때로 형변환을 우리 스스로가 하고 싶을 때도 있습니다. 

이를 위해 C 는 형변환 연산자를 제공합니다. 

 

 

형변환 연산자 기본 형식

 

 

단항 연산자 이기에 모든 이항 연산자보다 우선순위가 높습니다. 

 

보통 형변환 연산자는 3가지 경우를 위해 사용합니다. 

 

첫째 , 형변환을 문서화하여 코드의 가독성을 높힘. 

둘째 , 컴파일러를 거슬러 의도를 가지고 형변환

셋째 , overflow 예방

 

예시 코드 자리 (둘째 , 셋째 ~ ) 

 

5. pointer 와 array 사이에서 type decay(conversion)