C++ 초급 - 2. 기본 문법 (6 - 형 변환 (Type Conversion))
2025. 2. 12. 12:08ㆍ프로그래밍 언어/C++
2.6 형 변환 (Type Conversion)
C++에서 형 변환(Type Conversion)은 한 데이터 타입을 다른 데이터 타입으로 변환하는 과정이다.
형 변환에는 묵시적 변환(Implicit Conversion)과 명시적 변환(Explicit Conversion) 두 가지 방식이 있다.
(1) 묵시적 변환 (Implicit Conversion)
묵시적 변환은 컴파일러가 자동으로 수행하는 형 변환이다.
주로 작은 크기의 데이터 타입이 더 큰 크기의 데이터 타입으로 변환될 때 발생한다.
📌 자동 변환 규칙
C++에서는 다음과 같은 순서로 자동 변환이 발생한다.
char → int → float → double
즉, 더 큰 범위를 가지는 데이터 타입으로 변환되며, 데이터 손실이 발생하지 않는다.
📌 묵시적 변환 예제
#include <iostream>
int main() {
int num = 10;
double d = num; // int → double 자동 변환
std::cout << "정수 num: " << num << std::endl;
std::cout << "자동 변환된 실수 d: " << d << std::endl; // 10.0 출력
return 0;
}
🔹 출력 결과
정수 num: 10
자동 변환된 실수 d: 10
💡 설명
- int 타입의 num이 double 타입의 d로 변환됨.
- num 값이 10에서 10.0으로 변환되었지만, 데이터 손실은 없음.
📌 묵시적 변환 예제 (다양한 타입)
#include <iostream>
int main() {
char letter = 'A'; // 'A'는 ASCII 값 65
int num = letter; // char → int 자동 변환
float f = num; // int → float 자동 변환
double d = f; // float → double 자동 변환
std::cout << "char to int: " << num << std::endl; // 65 출력
std::cout << "int to float: " << f << std::endl; // 65.0 출력
std::cout << "float to double: " << d << std::endl; // 65.0 출력
return 0;
}
🔹 출력 결과
char to int: 65
int to float: 65
float to double: 65
💡 설명
- 'A'가 ASCII 코드 65로 변환됨 (char → int).
- int가 float로 변환될 때 소수점이 추가됨.
- float가 double로 변환될 때 데이터 손실 없이 변환됨.
(2) 명시적 변환 (Explicit Conversion)
명시적 변환은 프로그래머가 직접 타입 변환을 지정하는 방법이다.
이를 통해 데이터 손실을 방지하거나, 정확한 변환을 강제할 수 있다.
명시적 변환에는 다음과 같은 방식이 있다.
- C 스타일 변환 (타입)변수명
- C++ 스타일 변환 (static_cast<T>(변수명))
📌 C 스타일 변환 (비추천)
double pi = 3.14159;
int intPi = (int)pi; // 소수점 제거
std::cout << intPi; // 출력: 3
- 단점: 가독성이 떨어지고, reinterpret_cast와 같은 위험한 변환도 허용됨.
📌 C++ 스타일 변환 (static_cast)
#include <iostream>
int main() {
double pi = 3.14159;
int intPi = static_cast<int>(pi); // 소수점 제거
std::cout << "변환된 값: " << intPi << std::endl; // 출력: 3
return 0;
}
🔹 출력 결과
변환된 값: 3
💡 static_cast<T>(변수명)을 사용하는 이유
- C 스타일 변환보다 안전하고 명확함.
- 불필요한 변환을 방지할 수 있음.
- 컴파일러가 오류를 감지할 수 있음.
📌 static_cast 활용 예제
1. 정수 → 실수 변환
#include <iostream>
int main() {
int a = 7, b = 2;
double result = static_cast<double>(a) / b; // 정수 나눗셈을 실수 나눗셈으로 변환
std::cout << "7 / 2 = " << result << std::endl;
return 0;
}
🔹 출력 결과
7 / 2 = 3.5
💡 static_cast<double>(a)를 사용하지 않으면 7 / 2 = 3으로 출력됨.
2. 포인터 변환 (안전한 변환)
#include <iostream>
int main() {
int num = 10;
void* ptr = # // void 포인터로 변환
// static_cast를 사용하여 다시 int*로 변환
int* intPtr = static_cast<int*>(ptr);
std::cout << "포인터 변환된 값: " << *intPtr << std::endl;
return 0;
}
🔹 출력 결과
포인터 변환된 값: 10
💡 설명
- void*는 어떤 타입이든 가리킬 수 있는 범용 포인터.
- static_cast<int*>를 사용하여 원래 타입으로 변환.
📌 static_cast vs reinterpret_cast 차이점
- static_cast<T>(): 안전한 변환 (타입 변환 가능 여부를 컴파일러가 검사)
- reinterpret_cast<T>(): 메모리 해석 방식 자체를 변경 (위험할 수 있음)
int num = 42;
double* ptr = reinterpret_cast<double*>(&num); // 매우 위험한 변환
std::cout << *ptr; // 예상치 못한 결과 발생 가능
⚠️ reinterpret_cast는 메모리 해석 방식을 변경하기 때문에, 주의해서 사용해야 한다.
📌 static_cast vs dynamic_cast
변환 방식 | 설명 | 사용 예제 |
static_cast | 컴파일 시 타입 변환 | static_cast<int>(3.14) |
dynamic_cast | 런타임 타입 변환 (다형성) | dynamic_cast<Derived*>(basePtr) |
💡 dynamic_cast는 상속 관계에서 런타임 타입 변환을 수행할 때 사용되며, static_cast보다 비용이 크다.
정리
형 변환 종류 | 설명 | 예제 |
묵시적 변환 (Implicit) | 작은 타입 → 큰 타입 자동 변환 | int → double |
C 스타일 변환 (타입)변수 | C 방식 변환 (비추천) | (int)pi |
static_cast<T>() | 안전하고 명확한 변환 (추천) | static_cast<int>(3.14) |
reinterpret_cast<T>() | 메모리 주소 변환 (위험) | reinterpret_cast<int*>(ptr) |
dynamic_cast<T>() | 다형성 타입 변환 (런타임) | dynamic_cast<Derived*>(basePtr) |
'프로그래밍 언어 > C++' 카테고리의 다른 글
C++ 초급 - 3. 제어문 (2 - 반복문 (Loops)) (0) | 2025.02.12 |
---|---|
C++ 초급 - 3. 제어문 (1 - 조건문 (Conditional Statements)) (0) | 2025.02.12 |
C++ 초급 - 2. 기본 문법 (5 - 연산자 (Operators)) (0) | 2025.02.12 |
C++ 초급 - 2. 기본 문법 (4 - 주석 (Comments)) (0) | 2025.02.12 |
C++ 초급 - 2. 기본 문법 (3 - 기본 입출력 (Standard Input & Output)) (0) | 2025.02.12 |