C++ 为什么这个 reinterpret_cast 不能编译?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/2205353/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-27 22:31:31  来源:igfitidea点击:

Why doesn't this reinterpret_cast compile?

c++castingreinterpret-cast

提问by Vlad the Impala

I understand that reinterpret_castis dangerous, I'm just doing this to test it. I have the following code:

我知道这reinterpret_cast很危险,我只是为了测试它。我有以下代码:

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

When I try to compile the program, it gives me an error saying

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

invalid cast from type 'float' to type 'double

从“float”类型到“double”类型的无效转换

What's going on? I thought reinterpret_castwas the rogue cast that you could use to convert apples to submarines, why won't this simple cast compile?

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

采纳答案by John Dibling

By assigning y to the value returned by the cast you're not really casting the value x, you're converting it. That is, ydoesn't point to xand pretend that it points to a float. Conversion constructs a new value of type floatand assigns it the value from x. There are several ways to do this conversion in C++, among them:

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

The only real difference being the last one (an implicit conversion) will generate a compiler diagnostic on higher warning levels. But they all do functionally the same thing -- and in many case actuallythe same thing, as in the same machine code.

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

Now if you really do want to pretend that xis a float, then you really do want to cast x, by doing this:

现在,如果你真的想假装它x是一个浮点数,那么你真的想x通过这样做来投射:

#include <iostream>
using namespace std;

int main()
{
    int x = 42;
    float* pf = reinterpret_cast<float*>(&x);
    (*pf)++;
    cout << *pf;
    return 0;
}

You can see how dangerous this is. In fact, the output when I run this on my machine is 1, which is decidedly not 42+1.

可见这有多危险。事实上,当我在我的机器上运行它时的输出是1,这绝对不是 42+1。

回答by AnT

In C++ reinterpret_castcan only perform a specific set of conversions, explicitly listed in the language specification. In short, reinterpret_castcan only perform pointer-to-pointer conversions and reference-to-reference conversions (plus pointer-to-integer and integer-to-pointer conversions). This is consistent with the intent expressed in the very name of the cast: it is intended to be used for pointer/reference reinterpretation.

在 C++reinterpret_cast中只能执行一组特定的转换,在语言规范中明确列出。总之,reinterpret_cast只能执行指针到指针的转换和引用到引用的转换(加上指针到整数和整数到指针的转换)。这与演员表的名称所表达的意图是一致的:它旨在用于指针/引用重新解释。

What you are trying to do is not reinterpretation. If you want to reinterpret an intas a doubleyou'd have to convert it to a reference type

你要做的不是重新解释。如果要将 an 重新解释int为 a double,则必须将其转换为引用类型

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

although the equivalent pointer-based reinterpretation is probably more explicit

尽管等效的基于指针的重新解释可能更明确

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

Note though, that while reinterpret_castcan convert the reference/pointer types, the actual attempt to read the data through the resultant reference/pointer produces undefined behavior.

但请注意,虽然reinterpret_cast可以转换引用/指针类型,但通过结果引用/指针读取数据的实际尝试会产生未定义的行为。

And in any case this, of course, can't make much sense on a platform with intand doubleof different size (since in case of larger doubleyou will read beyond the memory occupied by x).

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

So, in the end it all boils down to what you were trying to achieve. Memory reinterpretation? See above. Some kind of more meaningful intto doubleconversion? If so, reinterpret_castwon't help you here.

所以,最终这一切都归结为你想要实现的目标。记忆重新诠释?看上面。某种更有意义intdouble转换?如果是这样,reinterpret_cast在这里帮不了你。

回答by R Samuel Klatchko

reinterpret_cast is not a general cast. According to the C++03 spec section 5.2.10.1:

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

Conversions that can be performed explicitly using reinterpret_cast are listed below. No other conversion can be performed explicitly using reinterpret_cast.

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

And there is nothing listed that describes converting between integral and floating point types (or between integral types, even this is illegal reinterpret_cast<long>(int(3));)

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

回答by finnw

If you are trying to convert the bits of your intto a the representation of a double, you need to cast the addressnot the value. You must also make sure the sizes match:

如果您试图将 your 的位转换int为 a 的表示double,则需要转换地址而不是值。您还必须确保尺寸匹配:

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

回答by David Rodríguez - dribeas

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:

另一件事是,它实际上是一个非常危险的转换,不仅是因为作为结果出现奇怪的值,或者上面的断言没有失败,而且因为如果类型的大小不同,并且您从“源”重新解释为'destination' 类型,对重新解释的引用/指针的任何操作都将访问sizeof(destination)字节。如果sizeof(destination)>sizeof(source)那将超出实际变量内存,可能会杀死您的应用程序或覆盖源或目标以外的其他变量:

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.
assert( t.y != 20 );

回答by Dominic Cooney

The compiler rejects what you wrote as nonsense because intand doublemay be objects with different sizes. You could achieve the same effect this way, although it is certainly dangerous:

编译器会拒绝你所写的无稽之谈,因为intdouble可能与不同大小的物体。您可以通过这种方式实现相同的效果,尽管这肯定是危险的:

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

This is potentially dangerous because if xand yare diffrent sizes (let's say intis four bytes and doubleis eight bytes) then when you dereference the eight bytes of memory at &xto fill in yyou will access four bytes of xand four bytes of ... whatever comes next in memory (possibly the start of y, or garbage, or something else entirely.)

这是潜在的危险,因为如果xy是不同的大小(假设int是四个字节和double八个字节)那么当您取消引用八个字节的内存&x以填充时,y您将访问四个字节x和四个字节的......无论接下来发生什么在内存中(可能是 的开始y,或垃圾,或其他完全不同的东西。)

If you want to convert a integer to a double, use a static_castand it will perform conversion.

如果要将整数转换为双精度数,请使用 astatic_cast它将执行转换。

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):

如果要访问 的位模式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]
}

回答by Alex B

reinterpret_castis best used for pointers. So a pointer to one object can be turned into a "submarine".

reinterpret_cast最好用于指针。因此,指向一个对象的指针可以变成“潜艇”。

From msdn:

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.

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

reinterpret_cast 的结果不能安全地用于除转换回其原始类型之外的任何其他事情。其他用途充其量是不可移植的。

回答by Matt Davis

Casting an int to a double doesn't require a cast. The compiler will perform the assignment implicitly.

将 int 转换为 double 不需要转换。编译器将隐式执行赋值。

The reinterpret_cast is used with pointers and references, e.g., casting an int *to a double *.

reinterpret_cast 与指针和引用一起使用,例如,将 an 转换int *为 a double *

回答by Andy White

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).

那很有意思。也许它在尝试将强制转换加倍之前进行了从 int 到 float 的隐式转换。int 和 float 类型的字节大小往往相同(当然取决于您的系统)。

回答by Evan Moran

The reinterpret approach led me down a strange path with inconsistent results. In the end I found it much better to memcpy like this!

重新解释的方法让我走上了一条奇怪的道路,结果不一致。最后我发现像这样 memcpy 更好!

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