Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/160.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 何时使用reinterpret_cast?_C++_Casting_Reinterpret Cast - Fatal编程技术网

C++ 何时使用reinterpret_cast?

C++ 何时使用reinterpret_cast?,c++,casting,reinterpret-cast,C++,Casting,Reinterpret Cast,我对reinterpret\u castvsstatic\u cast的适用性有点困惑。从我所读到的内容来看,当类型可以在编译时解释时,一般规则是使用静态强制转换,因此使用单词static。这是C++编译器内部使用的用于隐式转换的映射。 reinterpret\u casts适用于两种情况: 将整数类型转换为指针类型,反之亦然 将一种指针类型转换为另一种。我的总体想法是,这是不可移植的,应该避免 我有点困惑,我需要一个用法,我从C调用C++,C代码需要保存C++对象,所以基本上它持有空洞*/

我对
reinterpret\u cast
vs
static\u cast
的适用性有点困惑。从我所读到的内容来看,当类型可以在编译时解释时,一般规则是使用静态强制转换,因此使用单词
static
。这是C++编译器内部使用的用于隐式转换的映射。
reinterpret\u cast
s适用于两种情况:

  • 将整数类型转换为指针类型,反之亦然
  • 将一种指针类型转换为另一种。我的总体想法是,这是不可移植的,应该避免

我有点困惑,我需要一个用法,我从C调用C++,C代码需要保存C++对象,所以基本上它持有<代码>空洞*/COD>。在

void*
和类类型之间转换时应该使用什么类型转换


我看到了
static_cast
reinterpret_cast
的用法?虽然从我所读到的来看,
静态
更好,因为强制转换可以在编译时进行?虽然它说要使用
重新解释\u cast
从一种指针类型转换为另一种指针类型

读这本书!在C中保存C++数据可能有风险。
<>在C++中,一个对象的指针可以转换为<代码>空洞*>代码>,没有任何转换。但反过来说,情况并非如此。您需要一个<代码> STATICE-CASTEP>代码来获得原始指针。

< P> >代码> ReReTytC++ Studio<代码>不是由C++标准定义的。因此,从理论上讲,
重新解释cast
可能会使程序崩溃。在实践中,编译器会尝试执行您期望的操作,即解释您要传递的内容的位,就好像它们是您要转换到的类型一样。如果你知道你将要使用的编译器如何处理
reinterpret\u cast
,你可以使用它,但是说它是可移植的将是谎言

对于您描述的情况,并且几乎任何情况下,您可以考虑<代码> RealTytCase,可以使用<代码> StasyType Studio或其他替代方案。除其他事项外,本标准还规定了您对

静态播放的期望(§5.2.9):

类型为“指向cv void的指针”的右值可以显式转换为指向对象类型的指针。指针指向对象类型的值转换为“指针指向cv void”并返回到原始指针类型将具有其原始值


P> >对于您的用例,标准化委员会似乎有意为您使用<代码> STATICE-CASTEP>代码>

< P> C++标准保证如下:

int* a = new int();
void* b = reinterpret_cast<void*>(a);
int* c = reinterpret_cast<int*>(b);
static\u cast
ing指向和来自
void*
的指针将保留地址。也就是说,在以下情况下,
a
b
c
都指向同一地址:

int* a = new int();
void* b = static_cast<void*>(a);
int* c = static_cast<int*>(b);

a
c
包含相同的值,但
b
的值未指定。(实际上,它通常包含与
a
c
相同的地址,但标准中没有规定,并且在具有更复杂内存系统的机器上可能不是这样。)


对于从
void*
的转换,应首选
静态转换。

需要重新解释转换的一种情况是与不透明数据类型接口时。这在程序员无法控制的供应商API中经常发生。下面是一个人为的示例,其中供应商提供了一个用于存储和检索任意全局数据的API:

// vendor.hpp
typedef struct _Opaque * VendorGlobalUserData;
void VendorSetUserData(VendorGlobalUserData p);
VendorGlobalUserData VendorGetUserData();
要使用此API,程序员必须将其数据强制转换为
VendorGlobalUserData
,然后再转换回来<代码>静态\u cast
无效,必须使用
重新解释\u cast

// main.cpp
#include "vendor.hpp"
#include <iostream>
using namespace std;

struct MyUserData {
    MyUserData() : m(42) {}
    int m;
};

int main() {
    MyUserData u;

        // store global data
    VendorGlobalUserData d1;
//  d1 = &u;                                          // compile error
//  d1 = static_cast<VendorGlobalUserData>(&u);       // compile error
    d1 = reinterpret_cast<VendorGlobalUserData>(&u);  // ok
    VendorSetUserData(d1);

        // do other stuff...

        // retrieve global data
    VendorGlobalUserData d2 = VendorGetUserData();
    MyUserData * p = 0;
//  p = d2;                                           // compile error
//  p = static_cast<MyUserData *>(d2);                // compile error
    p = reinterpret_cast<MyUserData *>(d2);           // ok

    if (p) { cout << p->m << endl; }
    return 0;
}
模板
输出类型安全类型转换(输入类型指针)
{
void*temp=static_cast(指针);
返回静态铸件(温度);
}
我试图总结并使用模板编写了一个简单的安全转换。
请注意,此解决方案不保证在函数上强制转换指针。

您可以在编译时使用reinterprete_cast检查继承。
看这里:

如果要对(IEEE 754)浮点应用逐位运算,则可以使用reinterpret_cast。其中一个例子是快速平方根逆技巧:

它将浮点的二进制表示形式视为整数,将其右移并从常数中减去,从而将指数减半并取反。转换回浮点数后,将对其进行牛顿-拉斐逊迭代,以使此近似值更精确:

float Q_rsqrt( float number )
{
    long i;
    float x2, y;
    const float threehalfs = 1.5F;

    x2 = number * 0.5F;
    y  = number;
    i  = * ( long * ) &y;                       // evil floating point bit level hacking
    i  = 0x5f3759df - ( i >> 1 );               // what the deuce? 
    y  = * ( float * ) &i;
    y  = y * ( threehalfs - ( x2 * y * y ) );   // 1st iteration
//  y  = y * ( threehalfs - ( x2 * y * y ) );   // 2nd iteration, this can be removed

    return y;
}

这是最初用C语言编写的,所以使用C转换,但是类似C++的C++是RealTytPr.Case.

快速回答:使用代码> StasyCase<代码>编译,否则诉诸代码> RealTytRask .< /P> < p>第一,你有一些特定类型的数据,如int:这里/<

int x = 0x7fffffff://==nan in binary representation
然后,您希望访问与其他类型(如float)相同的变量: 你可以在两者之间做出决定

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

//this could only be used in cpp, looks like a function with template-parameters
简介:这意味着相同的内存被用作不同的类型。因此,您可以将浮点的二进制表示形式转换为int类型,如上文所述。例如,0x8000000为-0(尾数和指数为null,但符号msb为1。这也适用于双精度和长双精度

优化:我认为在许多编译器中,reinterpret_cast会得到优化,而c-cast是由PointerArtihmetic实现的(值必须复制到内存中,因为指针不能指向cpu寄存器)

注意:在这两种情况下,您都应该在强制转换之前将强制转换的值保存在变量中!此宏可以帮助:

#define asvar(x) ({decltype(x) __tmp__ = (x); __tmp__; })

简短的回答:
如果你不知道reinterpret\u cast
代表什么,不要使用它。如果你将来需要它,你会知道的

完整答案:

让我们考虑基本的数字类型。

例如,当您将
int(12)
转换为
unsigned float(12.0f)
时,您的处理器需要inv
float y = reinterpret_cast<float&>(x);

//this could only be used in cpp, looks like a function with template-parameters
float y = *(float*)&(x);

//this could be used in c and cpp
#define asvar(x) ({decltype(x) __tmp__ = (x); __tmp__; })
/*constexpr*/ bool is_little_endian() {
  std::uint16_t x=0x0001;
  auto p = reinterpret_cast<std::uint8_t*>(&x);
  return *p != 0;
}
#include <iostream>
#include <string>
#include <iomanip>
using namespace std;

class A
{
public:
    int i;
};

class B : public A
{
public:
    virtual void f() {}
};

int main()
{
    string s;
    B b;
    b.i = 0;
    A* as = static_cast<A*>(&b);
    A* ar = reinterpret_cast<A*>(&b);
    B* c = reinterpret_cast<B*>(ar);
    
    cout << "as->i = " << hex << setfill('0')  << as->i << "\n";
    cout << "ar->i = " << ar->i << "\n";
    cout << "b.i   = " << b.i << "\n";
    cout << "c->i  = " << c->i << "\n";
    cout << "\n";
    cout << "&(as->i) = " << &(as->i) << "\n";
    cout << "&(ar->i) = " << &(ar->i) << "\n";
    cout << "&(b.i) = " << &(b.i) << "\n";
    cout << "&(c->i) = " << &(c->i) << "\n";
    cout << "\n";
    cout << "&b = " << &b << "\n";
    cout << "as = " << as << "\n";
    cout << "ar = " << ar << "\n";
    cout << "c  = " << c  << "\n";
    
    cout << "Press ENTER to exit.\n";
    getline(cin,s);
}