据我所知,reinterpret_cast是危险的,我只是在做这个测试吧。我有以下代码:

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

当我试图编译程序,它给了我一个错误说

  

这类型“浮动”无效的转换为类型“双

这是怎么回事?我以为reinterpret_cast是流氓投,你可以用它来苹果转换为潜艇,为什么不会这样简单的投编译?

有帮助吗?

解决方案

通过指定y以由你没有真正精铸人的价值x剧组返回的值,你将它转换。也就是说,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作为double你必须将其转换为引用类型

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

虽然等效基于指针的重新解释可能是更明确的

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

请注意虽然,而reinterpret_cast可以转换基准/指针类型,实际尝试通过将得到的参考读出的数据/指针产生不确定行为。

在任何情况下这一点,当然,不能与int和不同大小的double平台上多大意义(因为在较大double的情况下,你会读超出x占用的内存)。

那么,到底这一切都归结到是你所想要的目的。内存重新解释?往上看。某种更有意义intdouble转换?如果是这样,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);

在编译器会拒绝你所写的无稽之谈,因为intdouble可以是具有不同尺寸的对象。你可以达到同样的效果这样,虽然它肯定是危险的:

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

这是潜在的危险,因为如果xy是不同势的大小(假设int是四个字节,并将double是八个字节),那么当你提领的八个字节的&x填补y内存,您将访问四个字节x的和四个字节的...在存储器下一任何到来时(y的可能的开始,或垃圾,或别的东西完全。)

如果你想一个整数转换为双,使用static_cast,它会进行转换。

如果要访问x的位模式,转换为一些方便的指针类型(比如,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]
}

重释铸造允许你重新解释的存储器块为不同类型。这必须在指针的或引用执行

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

另一件事是,它实际上是一个相当危险的演员,这不仅是因为出来的结果,或断言上面没有失败,而是因为如果类型是不同的尺寸,并从重新解读“怪值源”到‘目的地’的类型,在重新解释参考/指针的任何操作将访问sizeof(destination)字节。如果sizeof(destination)>sizeof(source)然后,将步骤超出了实际可变存储器,有可能杀死应用程序或overwritting比源或目的地等其它变量:

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最好用于指针。因此,一个指针到一个对象可以变成一个“潜艇”。

MSDN

  

在reinterpret_cast运算符可以是   用于转化如char *到   INT *,或One_class *到   Unrelated_class *,它本质上是   不安全的。

     

一个的reinterpret_cast的结果   不能安全地用于任何   不是被强制转换回其他公司   原始类型。其他用途的,在   最好,不可移植的。

在重新解释的做法使我打倒见异思迁结果一个奇怪的路径。最后,我发现它要好得多memcpy的这个样子!

double source = 0.0;
uint64_t dest;
memcpy(&dest, &source, sizeof(dest));

铸造一个int到双不需要铸造。编译器将隐式地执行分配。

在的reinterpret_cast使用具有指针和引用,例如,铸造int *double *

这是有趣的。也许它做的隐式转换从int浮动它试图投翻番了。 int和float类型往往是在字节相同的尺寸(取决于你当然系统)。

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top