19

我知道 C++ 中的reinterpret_cast可以这样使用:

float a = 0;
int b = *reinterpret_cast<int*>(&a);

但是为什么不能直接施法呢?

float a = 0;
int b = reinterpret_cast<int>(a);

error: invalid cast from type 'float' to type 'int'
4

5 回答 5

38

reinterpret_cast所做的只是让您以不同的方式读取您传递的内存。你给它一个内存位置,并要求它读取该内存,就好像它是你要求它读的一样。这就是为什么它只能与指针和引用一起使用。

我们以这段代码为例:

#include <iostream>

int main()
{
    float a = 12;
    int b = *reinterpret_cast<int*>(&a);

    std::cout << b;
}

因此,要将这行代码分解为更多细节*reinterpret_cast<int*>(&a);

  1. 取地址a
  2. reinterpret_cast对一个int*
  3. 取回一个int*指向a
  4. 将返回的指针的值推迟为int

现在,当我运行它时,我得到1094713344了 12 的原因,因为float使用 IEEE 表示为0100 0001 0100 0000 0000 0000 0000 0000二进制。现在把那个二进制文件读为unsigned int,然后你最终得到1094713344.

这就是为什么reinterpret_cast被认为是非常危险的,为什么不应该在这种情况下使用它。

只有当您有一个指向内存的指针并且您需要以某种方式读取该内存并且您知道可以以这种方式读取内存时,您才应该使用它。

于 2013-08-31T06:04:59.570 回答
12

在您给出的情况下,您不能 reinterpret_cast ,因为 reinterpret_cast 只需要一个 int 来转换为指针,或者相反,并遵循其他类似的规则。

那里有这些规则的摘要:http: //en.cppreference.com/w/cpp/language/reinterpret_cast

于 2013-08-31T15:36:37.257 回答
4

为什么不能直接投射?

我相信这是一个纯粹的设计决定,使C++ 比 C 更安全

reinterpret_cast非常危险,因为它可能涉及类型别名,这是未定义行为的一种捷径。当您使用 C++ 强制转换时,您会与编译器签订“我知道,我在做什么”的合同。所以,所有这些长运算符名称、尖括号、类型指针类型转换都在告诉你:“等等,不要这样做。也许你的代码设计有问题!”。

此外,并非所有 C++ 编译器都允许类型别名(通过强制转换或联合实现)。

于 2013-08-31T06:17:06.973 回答
3

在第二种情况下,它不是从值a转换为b。事实上,这只是一种转换。b不会指向x并假装它指向一个浮点数。Conversion 构造一个 int 类型的新值,并将其赋值为 from a

有几种方法可以在 C++ 中正确地进行这种转换。

一种是像往常一样简单地使用静态转换。这是推荐的解决方案:

int b = static_cast<int>(a);

您可以通过以下方式使用 reinterpret_cast。请注意,这是对位模式的重新解释,而不是与提到的替代方案不同的转换:

int b = reinterpret_cast<int&>(a);

您还可以使用 C 样式转换:

int b = (int)a;

您还可以使用 C++ 函数样式转换:

int b = int(a);

您也可以获得隐式对话,尽管它可能会产生警告:

int b = a;

在这种特殊情况下建议使用静态转换,但至少不要使用隐式对话,也不要使用 C++ 中的 C 样式。

于 2013-08-31T05:48:18.083 回答
2

您可以将reinterpret_cast指针类型转换为任何其他指针类型,例如,您可以将float指针转换为int指针:

float *a = new int(0);
int* b = reinterpret_cast<int*>(a);
于 2013-08-31T05:46:19.020 回答