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
vsstatic\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);
}