为什么不这reinterpret_cast编译?

我明白reinterpret_cast是危险的,我只是做这个来testing它。 我有以下代码:

int x = 0; double y = reinterpret_cast<double>(x); 

当我尝试编译程序时,它给我一个错误说

 invalid cast from type 'float' to type 'double 

这是怎么回事? 我以为reinterpret_cast是你可以用来将苹果转换成潜艇的stream氓演员,为什么这个简单的演员不能编译?

通过将y分配给演员返回的值,您并不是真正投射值x ,而是将其转换。 也就是说, y不指向x并假装它指向一个浮点数。 转换构造一个新的floattypes的值,并为其赋值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; } 

唯一真正的区别是最后一个(隐式转换)将生成更高警告级别的编译器诊断。 但是他们都在function上做同样的事情 – 在许多情况下, 实际上是相同的东西,在相同的机器代码。

现在如果你真的想假装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只能执行指针到指针的转换和引用到引用的转换(加上指针到整数和整数到指针的转换)。 这与演员的名字所expression的意图是一致的:意图用于指针/参考重新解释。

你试图做的不是重新解释。 如果你想重新解释一个intdouble你必须将其转换为引用types

 double y = reinterpret_cast<double&>(x); 

尽pipe等价的基于指针的重新解释可能更加明确

 double y = *reinterpret_cast<double*>(&x); // same as above 

请注意虽然reinterpret_cast可以转换参考/指针types,但实际尝试通过生成的参考/指针读取数据会产生未定义的行为。

在任何情况下,当然,在一个intdouble大小不同的平台上(因为在double情况下,你会读取x以上的内存)。

所以最终都归结为你想要达到的目标。 内存重新解释? 往上看。 一些更有意义的int double转换? 如果是这样, reinterpret_cast不会帮你在这里。

reinterpret_cast不是一般的演员。 根据C ++ 03规范第5.2.10.1节:

下面列出了可以使用reinterpret_cast明确执行的转换。 使用reinterpret_cast不能显式执行其他转换。

并没有列出任何描述在整型和浮点types之间转换(或整型之间的转换,即使这是非法的reinterpret_cast<long>(int(3));

如果你想把int的位转换成double的表示forms,你需要把地址转换成不是这个值。 您还必须确保尺寸匹配:

 uint64_t x = 0x4045000000000000; double y = *reinterpret_cast<double *>(&x); 

编译器拒绝你写的东西是无稽之谈,因为intdouble可能是不同大小的对象。 你可以用这种方法达到同样的效果,虽然这肯定是危险的:

 int x = 0; double y = *reinterpret_cast<double*>(&x); 

这是潜在的危险,因为如果xy是不同的大小(假设int是四个字节, double是八个字节),那么当你在&x取消八个字节的内存填充时,你将访问四个字节的x和四个字节…的内容(可能是y的开始,或者垃圾,或者其他的东西)。

如果要将整数转换为double,请使用static_cast并执行转换。

如果你想访问x的位模式,可以使用一些方便的指针types(比如说byte* ),并访问sizeof(int) / sizeof(byte)

 byte* p = reinterpret_cast<byte*>(&x); for (size_t i = 0; i < sizeof(int); i++) { // do something with p[i] } 

重新解释转换允许您重新解释为不同types的内存块。 这必须在指针或引用上执行:

 int x = 1; float & f = reinterpret_cast<float&>(x); assert( static_cast<float>(x) != f ); // !! 

另一件事情是,这实际上是一个相当危险的演员,不仅是因为奇怪的价值观作为结果出现,或者上面断言没有失败,而是因为如果types是不同的大小,你重新解释从“源”到'destination'types,对重新解释的引用/指针的任何操作都将访问sizeof(destination)字节。 如果sizeof(destination)>sizeof(source)那么这将超出实际的variables内存,可能会导致应用程序中断或覆盖源或目标之外的其他variables:

 struct test { int x; int y; }; test t = { 10, 20 }; double & d = reinterpret_cast<double&>( tx ); d = 1.0/3.0; assert( tx != 10 ); // most probably at least. asswet( ty != 20 ); 

reinterpret_cast最适合用于指针。 所以指向一个对象的指针可以变成一个“潜艇”。

从msdn :

reinterpret_cast运算符可用于转换,如char *到int *或One_class *到Unrelated_class *,这本质上是不安全的。

reinterpret_cast的结果不能安全地用于除了被转换回原始types以外的其他任何东西。 其他用途充其量不适用。

将一个int转换为double不需要转换。 编译器将隐含地执行分配。

reinterpret_cast用于指针和引用,例如,将int *转换为double *

那很有意思。 也许这是做一个从int到float的隐式转换,然后再试图转换成double。 int和floattypes的字节大小一样(取决于你的系统当然)。