이 reinterpret_cast가 컴파일되지 않는 이유는 무엇입니까?
reinterpret_cast
위험하다는 것을 이해 합니다. 테스트를 위해이 작업을 수행하고 있습니다. 다음 코드가 있습니다.
int x = 0;
double y = reinterpret_cast<double>(x);
프로그램을 컴파일하려고하면 오류가 발생합니다.
'float'유형에서 'double 유형으로의 잘못된 캐스트
무슨 일이야? reinterpret_cast
사과를 잠수함으로 변환하는 데 사용할 수있는 불량 캐스트 라고 생각 했는데이 간단한 캐스트가 컴파일되지 않는 이유는 무엇입니까?
캐스트에 의해 반환 된 값에 y를 할당하면 실제로 값을 캐스팅하지 않고 x
변환하는 것입니다. 즉, float를 가리키는 척 y
하지 않습니다 x
. 변환은 유형의 새 값을 생성하고에 값을 float
할당합니다 x
. C ++에서이 변환을 수행하는 방법에는 여러 가지가 있습니다.
int main()
{
int x = 42;
float f = static_cast<float>(x);
float f2 = (float)x;
float f3 = float(x);
float f4 = x;
return 0;
}
유일한 실제 차이점은 마지막 것 (암시 적 변환)이 더 높은 경고 수준에서 컴파일러 진단을 생성합니다. 그러나 그들은 모두 기능적으로 같은 일을 - 그리고 많은 경우에 실제로 같은 일, 같은 컴퓨터 코드로.
이제 정말로 그것이 x
float 인 척하고 싶다면 다음을 수행하여 실제로 캐스트하고 싶습니다 x
.
#include <iostream>
using namespace std;
int main()
{
int x = 42;
float* pf = reinterpret_cast<float*>(&x);
(*pf)++;
cout << *pf;
return 0;
}
이것이 얼마나 위험한지 알 수 있습니다. 사실, 이것을 내 컴퓨터에서 실행할 때의 출력 1
은 42 + 1이 아닙니다.
C ++에서는 reinterpret_cast
언어 사양에 명시 적으로 나열된 특정 변환 집합 만 수행 할 수 있습니다. 요컨대, reinterpret_cast
포인터-포인터 변환 및 참조-참조 변환 (포인터-정수 및 정수-포인터 변환 포함) 만 수행 할 수 있습니다. 이것은 캐스트의 바로 이름에 표현 된 의도와 일치합니다. 이것은 포인터 / 참조 재 해석에 사용하기위한 것입니다.
당신이하려는 것은 재 해석이 아닙니다. 당신이 재 해석하려면 int
A와를 double
당신은 참조 형식으로 변환해야 할 것
double y = reinterpret_cast<double&>(x);
동등한 포인터 기반 재 해석이 아마도 더 명시 적이지만
double y = *reinterpret_cast<double*>(&x); // same as above
reinterpret_cast
참조 / 포인터 유형을 변환 할 수 있지만 결과 참조 / 포인터를 통해 데이터를 읽으려는 실제 시도는 정의되지 않은 동작을 생성합니다.
그리고 어떤 경우에이은 물론, 함께 플랫폼에 많은 이해가되지 수 int
및 double
(큰 경우 이후 다른 크기의 double
메모리에 의해 점령 이상으로 읽을 것 x
).
그래서 결국 모든 것은 당신이 달성하고자했던 것에 귀결됩니다. 기억 재 해석? 위 참조. 더 의미의 일종 int
으로 double
변환? 그렇다면 reinterpret_cast
여기서 도움이되지 않습니다.
reinterpret_cast는 일반적인 캐스트가 아닙니다. C ++ 03 사양 섹션 5.2.10.1에 따르면 :
reinterpret_cast를 사용하여 명시 적으로 수행 할 수있는 변환은 다음과 같습니다. reinterpret_cast를 사용하여 명시 적으로 다른 변환을 수행 할 수 없습니다.
그리고 정수와 부동 소수점 유형 간 (또는 정수 유형 간 변환을 설명하는 목록이 없습니다. 이는 불법입니다 reinterpret_cast<long>(int(3));
)
의 비트를 int
의 표현 으로 변환하려는 경우 값이 아닌 주소double
를 캐스팅해야 합니다. 또한 크기가 다음과 일치하는지 확인해야합니다.
uint64_t x = 0x4045000000000000;
double y = *reinterpret_cast<double *>(&x);
컴파일러는 당신이 때문에 말도 쓴 것을 거부 int
와 double
크기가 다른 객체 일 수 있습니다. 확실히 위험하지만이 방법으로 동일한 효과를 얻을 수 있습니다.
int x = 0;
double y = *reinterpret_cast<double*>(&x);
This is potentially dangerous because if x
and y
are diffrent sizes (let's say int
is four bytes and double
is eight bytes) then when you dereference the eight bytes of memory at &x
to fill in y
you will access four bytes of x
and four bytes of ... whatever comes next in memory (possibly the start of y
, or garbage, or something else entirely.)
If you want to convert a integer to a double, use a static_cast
and it will perform conversion.
If you want to access the bit-pattern of x
, cast to some convenient pointer type (say, byte*
) and access up to sizeof(int) / sizeof(byte)
:
byte* p = reinterpret_cast<byte*>(&x);
for (size_t i = 0; i < sizeof(int); i++) {
// do something with p[i]
}
Reinterpret cast allows you to reinterpret a block of memory as a different type. This has to be performed on pointers or references:
int x = 1;
float & f = reinterpret_cast<float&>(x);
assert( static_cast<float>(x) != f ); // !!
The other thing is that it is in fact a quite dangerous cast, not only due to strange values coming out as results, or the assert above not failing, but because if the types are of different sizes, and you reinterpret from 'source' to 'destination' types, any operation on the reinterpreted reference/pointer will access sizeof(destination)
bytes. If sizeof(destination)>sizeof(source)
then that will step beyond the actual variable memory, potentially killing your application or overwritting other variables other than the source or destination:
struct test {
int x;
int y;
};
test t = { 10, 20 };
double & d = reinterpret_cast<double&>( t.x );
d = 1.0/3.0;
assert( t.x != 10 ); // most probably at least.
asswet( t.y != 20 );
reinterpret_cast
is best used for pointers. So a pointer to one object can be turned into a "submarine".
From msdn:
The reinterpret_cast operator can be used for conversions such as char* to int*, or One_class* to Unrelated_class*, which are inherently unsafe.
The result of a reinterpret_cast cannot safely be used for anything other than being cast back to its original type. Other uses are, at best, nonportable.
The reinterpret approach led me down a strange path with inconstant results. In the end I found it much better to memcpy like this!
double source = 0.0;
uint64_t dest;
memcpy(&dest, &source, sizeof(dest));
Casting an int to a double doesn't require a cast. The compiler will perform the assignment implicitly.
The reinterpret_cast is used with pointers and references, e.g., casting an int *
to a double *
.
That's interesting. Maybe it's doing an implicit conversion from int to float before it attempts the cast to double. int and float types tend to be the same size in bytes (depending on your system of course).
참고URL : https://stackoverflow.com/questions/2205353/why-doesnt-this-reinterpret-cast-compile
'IT박스' 카테고리의 다른 글
시퀀스 다이어그램에서 여러 스레드를 설명하는 방법은 무엇입니까? (0) | 2020.12.02 |
---|---|
Django에서 AngularJS를 사용하는 모범 사례는 무엇입니까? (0) | 2020.12.02 |
iPhone UIWebView를 사용할 때 Asp.Net 양식 인증 (0) | 2020.12.01 |
Style과 ControlTemplate의 차이점 (0) | 2020.12.01 |
Assets 폴더의 파일에 Android 경로 문자열을 가져 오는 방법은 무엇입니까? (0) | 2020.12.01 |