[C++] Type Casting 연산자 정리 static, dynamic,reinterpret, const
모든 데이터는 바이너리 데이터로 이루어진다.
포인터에 대한 형변환은 언어에게 그냥 해당 주소안에 있는 데이터를 이 형태로 취급해라 라는 정도이다.
그래서 어떤 어드레스에 대해 역참조를 하면 포인터의 형태가 int* 이면 4byte를 읽어들이고,
long long 형이면 8byte를 읽어 들이는 것 뿐이다.
다만 이런 캐스트 연산자를 사용하는 이유는
언어 차원에서 뭔가 의도한건 아닌거 같은데? 정도를 잡아내게끔 할때이다.
1. static_cast
int* From = new int;
void* To = static_cast<double*>(From);
//No.
int* From = new int;
void* To = static_cast<long long*>(From);
//No.
long long* From = new long long;
void* To = static_cast<short*>(From);
//No.
int* From = new int;
void* To = static_cast<float*>(From);
//No.
double* From = new double;
void* To = static_cast<float*>(From);
//No.
double* From = new double;
void* To = static_cast<long long*>(From);
//No.
double* From = new double;
void* To = static_cast<int*>(From);
//Yes.
float* From = new float;
void* To = static_cast<int*>(From);
//Yes.
long long* From = new long long;
void* To = static_cast<int*>(From);
//Yes.
static_cast는 컴파일시 잘못된 형변환에 대해 오류를 컴파일 타임에 잡기위해 사용한다.
마치 컴파일러에게 "static_cast 쓴다 ? 네가 보았을때 이상하다 싶으면 알려줘라" 하는 것과 같다.
그러니 버퍼에서의 오프셋 접근 등 상황에서는 static_cast는 사용하지 않는다.
처음에는 자료형의 크기가 이전 포인터 형보다 이후 포인터형의 실 자료형 크기가 더 크면
형변환을 못하게 막는 줄 알았는데, 그것도 아닌게 long long* 은 float* 로 변환이 안된다.
double* 에서 float* 로의 형변환은 지수부와 가수부의 크기가 달라 자칫 잘못된 값을 역참조 할까봐
막아주는 듯 하다.
double* 에서 int* 는 잘 되는데? 기준은 애매하다.
아무튼 일반적인 상황에서의 실수를 막고 싶다면 static_cast를 사용한다.
2. dynamic_cast
런타임시에 상속관계가 명확한지 알아내고 싶을때 사용한다.
포인터 형은 별 의미가 없고, 메모리에 실제로 어떤 값이 있는 지가 중요하다.
상속 관계시에도, private 상속이나 protected 상속의 경우에는 실패한다.
Parent* From = new Child;
void* To = dynamic_cast<Child*>(From);
//Yes.
Child* From = new Child;
void* To = dynamic_cast<Parent*>(From);
//Yes.
void* From = new Child;
void* To = dynamic_cast<Parent*>(From);
//Yes void* 형인데 왜 되나요? 해당 주소 메모리에 어떤 객체가 있는지를 체크할꺼니까요 ^^.
//Okay ~
Parent* From = new Parent;
void* To = dynamic_cast<Child*>(From);
//No. 실제 객체는 상위 클래스이다.
NotAChild* From = new NotAChild;
void* To = dynamic_cast<Parent*>(From);
//No. 상속관계 아님.
void* From = new NotAChild;
void* To = dynamic_cast<Parent*>(From);
//No. 상속관계 아님. 포인터 형은 중요하지 않다. 메모리에 실제로 그 타입이 들어가 있는가가 중요.
3. const_cast
const 를 떼내고 싶을때 사용한다.
int* Convert = (int*)&A;
//C Style.
int* Convert = const_cast<int*>(&A);
//C++ const.
4. reinterpret_cast
사실상 C Style과 같다.
보통 메모리에 접근에 대한 오프셋을 마음대로 지정한다음 특정 바이트 수만큼 해당 형태로 읽게끔 할때사용한다.
int* A = new int;
*A = 0x12345678;
//테스팅 중인 내 머신은 리틀엔디안이다.
printf("%0x\n", *(reinterpret_cast<char*>(A) + 1));
//56
printf("%0x\n", *(reinterpret_cast<char*>(A) + 2));
//34
printf("%0x\n", *reinterpret_cast<short*>(A));
//5678
'C++' 카테고리의 다른 글
[C++] C++11 constexpr (0) | 2022.03.20 |
---|---|
[C++] 스마트 포인터 unique_ptr, shared_ptr, weak_ptr (0) | 2022.03.19 |
[C++] C++ 11 Argument로 전달된 정적 배열의 크기 (0) | 2022.03.05 |
[C++] C++11 Parameter Pack 사용하기 (0) | 2022.03.05 |
[C++] C++ new 연산자 오버로딩을 이용한 메모리 풀 만들기 (0) | 2022.01.27 |
댓글
이 글 공유하기
다른 글
-
[C++] C++11 constexpr
[C++] C++11 constexpr
2022.03.20 -
[C++] 스마트 포인터 unique_ptr, shared_ptr, weak_ptr
[C++] 스마트 포인터 unique_ptr, shared_ptr, weak_ptr
2022.03.19 -
[C++] C++ 11 Argument로 전달된 정적 배열의 크기
[C++] C++ 11 Argument로 전달된 정적 배열의 크기
2022.03.05 -
[C++] C++11 Parameter Pack 사용하기
[C++] C++11 Parameter Pack 사용하기
2022.03.05