형변환과 형변환 연산자

정의

  • 형변환 : 식의 자료형을 다른 자료형으로 바꾸는 것
  • 형변환 연산자 : 명시적으로 형변환을 지시하는 연산자

형변환의 종류

형변환의 종류

형변환 종류 설명
명시적 형변환 형변환 연산자를 통해 특정 자료형으로 변환
묵시적 형변환 특별히 형변환 연산자를 사용하지 않아도, 연산이 가능한 자료형으로 자동적으로 이루어지는 형변환

명시적 형변환

명시적 형변환의 표현 형식

1
2
3
4
(typename)expr
// typename : 변환할 자료형
// expr : 자료형을 변환할 식 (수식, 변수, 값 등)
// 결과값 : expr 을 typename형으로 변환한 값

명시적 형변환의 종류

형식 변환 대상 자료형 설명
(typename)    
(int) 정수형 (int) 실수형에서 소수점 이하를 버리고 정수 부분만 취하거나, 다른 정수형으로 변환합니다.
(float) 실수형 (float) 정수형을 단정밀도 실수로 변환하여 사용합니다.
(double) 실수형 (double) 정수형을 배정밀도 실수로 변환합니다. (흔히 나눗셈에 사용)
(char) 문자형/정수형 (char) 값을 1바이트 크기의 문자로 변환합니다. (ASCII/유니코드 값)
(short) 정수형 (short) 값을 2바이트 정수로 변환합니다.
(long) 정수형 (long) 값을 긴 정수형으로 변환합니다.
(void*) 포인터 (void*) 특정 자료형 없이 메모리 주소를 나타내는 범용 포인터로 변환합니다.
(자료형*) 포인터 (Type*) 특정 자료형(int*, struct* 등)의 포인터로 변환합니다.

예시

1
2
3
4
5
6
7
8
9
10
void type_cast_operator(){
	int a = 3, b = 4;
	double c;
	
	c = a / b;
	printf("a / b 나눗셈 결과         : %f\n", c);
	
	c = (double)a / b;
	printf("(double) a / b나눗셈 결과 : %f\n", c);
}
1
2
b 나눗셈 결과             : 0.000000
(double) a / b나눗셈 결과 : 0.750000

위 예시의 두 가지 수식을 풀이하면 다음과 같다.

첫 번째 수식
(1) int a / int b = 3/4
(2) = 0
(3) c = (double) 0
(4) c = 0.000000

두 번째 수식
(1) (double) 3 = 3.000000
(2) 3.000000 / int 4 (명시적 형변환)
(3) 3.000000 / 4.000000 (묵시적 형변환)
(4) c = 0.750000

묵시적 형변환

묵시적 형변환의 정의

  • 특별히 형변환 연산자를 사용하지 않아도, 연산이 가능한 자료형으로 자동적으로 이루어지는 형변환

묵시적 형변환의 표현 형식

  • 묵시적 형변환은 별도 표현 형식이 없다. 표현하지 않는다.

묵시적 형변환의 종류

묵시적 형변환 설명
승격 (확대변환)
Promotion
가장 효율적인 자료형보다 작은 자료형이 효율적인 처리를 위해 더 큰 자료형으로 변환되는 것.
정수형 승격(integer promotion), 부동소수점 승격(floating point -)이 있다.
정수형 승격 : char, short => 연산시 int 로 자동 승격됨
부동소수점 승격 : float => 연산시 double 로 자동 승격됨
연산 순서에 따라 꼭 필요한 지점에서 형변환 연산지 진행된다.
일반 산술 변환 서로 다른 자료형이 혼재하는 식에서 표현 범위가 더 큰 자료형으로 변환됨
컴파일러가 두 피연산자 중 더 큰(높은 순위의) 자료형으로 맞춘다.
대입 변환 대입 연산자가 사용될 때, 우변이 좌변의 자료형에 맞춰 자동 변환되는 것.
이 변환은 데이터 손실 가능성이 있다.
함수 호출 변환 함수 호출시 입력 인수가 함수의 매개변수 자료형으로 자동 변환되는 것.
대입 변환과 유사하게 작동한다.

승격과 일반 산술 변환은 다르다.
승격은, “가장 효율적인 연산이 가능한 자료형(int, double)”로 데이터를 처리하기 위함 이며
때문에, 데이터의 손실이 없는 선에서 특정 값 자체를 형변환 시킨다.
때문에 정수형에서는 int 보다 작은 char, unsigned char, short, unsigned short 이 int, unsigned int 형으로 변환되며
부동소수형에서는 double 보다 작은 float 형이 우선 double 형으로 변환된 뒤 연산이 시작된다.
자세한 내용은 아래 예시를 참고한다.

예시

  • 승격 (확대 변환)
1
2
3
4
5
6
7
8
9
10
11
12
13
// 1. 승격 확대 변환 (Promotion)
// char c는 **연산에 참여하기 전에** int로 확대 변환된다.
char c1 = 10;
char c2 = 50;

char result_c = c1 + c2; 
printf("1. 확대 변환 (char + char): %d\n", result_c);
printf("산술연산이 수행되기 전에, 각 char 는 int 형으로 변환된다.\n");

printf("---------------------------------------------");
printf("(1) result_c = (int)c1 + (int)c2;");
printf("(2) result_c = 10 + 50; (10과 50 모두 int 형)");
printf("(3) result_c = 60; (60은 int 형)");
1
2
3
4
5
6
7
# 출력
1. 확대 변환 (char + char): 60 (char가 int로 변환됨)
산술연산이 수행되기 전에, 각 char 는 int 형으로 변환된다.
---------------------------------------------
(1) result_c = (int)c1 + (int)c2;
(2) result_c = 10 + 50; (10과 50 모두 int 형)
(3) result_c = 60; (60은 int 형)


  • 일반 산술 변환
1
2
3
4
5
6
7
8
// 2. 일반 산술 변환 (Usual Arithmetic Conversions)
// 승격(char -> int) 후, int와 float 중 더 정밀한 float으로 통일된다.
char c = 10;
float f = 20.5f;
float result_a = c + f;
printf("2. 일반 산술 변환 (char + float): %.1f\n", result_a);
printf("(1) char 는 우선 int 형으로 승격된다. 수식은 int + float 이 된다.\n");
printf("(2) int + float 에서 더 정밀한 float 형으로 자료형이 통일된다.");
1
2
3
4
# 출력
2. 일반 산술 변환 (char + float): 30.5
(1) char 는 우선 int 형으로 승격된다. 수식은 int + float 이 된다.
(2) int + float 에서 더 정밀한 float 형으로 자료형이 통일된다.


  • 대입 변환
1
2
3
4
5
6
7
8
9
10
11
12
13
// 3. 대입 변환 (Assignment Conversion)
// 큰 double 변수에 작은 float 값을 대입하면 float이 double로 자동 확대 변환된다.
// 이 경우 형변환은 데이터 손실이 없다.
float f = 20.5f;
double d;
d = f;
printf("3. 대입 변환 (float -> double): %.2f (확대 변환)\n", d);

// 작은 int 변수에 큰 float 값을 대입하면 float의 소수점 이하가 버려진다.
// 즉, 데이터 손실이 발생한다.
int small_i;
small_i = f;
printf("3. 대입 변환 (float -> int)   : %d (축소 변환, 소수점 버림)\n", small_i);
1
2
3. 대입 변환 (float -> double): 20.50 (확대 변환)
4. 대입 변환 (float -> int)   : 20 (축소 변환, 소수점 버림)


  • 함수 호출 변환
1
2
3
4
5
6
7
8
9
void print_int_to_double(int a){
	printf("print int to double : %lf", a);
	printf("and how about int..? : %d", a);
}

void main(){
	double its_double = 3.14;
	print_int_to_double(its_double);
}
1
2
print int to double  : 0.000000
and how about int..? : 3

Reference

C 프로그래밍 (김형근, 곽덕훈, 정재화 공저)
C 프로그래밍 강의 (방송통신대 - 이병래)

Comments