当两个链接的static_cast可以完成它的工作时,为什么我们在C++中使用reinterpret_cast?

Naw*_*waz 40 c++ casting static-cast reinterpret-cast

说我想投A*,char*反之亦然,我们有两个选择(我的意思是,我们很多人认为我们有两个选择,因为两者似乎都有效!因此混乱!):

struct A
{
    int age;
    char name[128];
};

A a;
char *buffer = static_cast<char*>(static_cast<void*>(&a)); //choice 1
char *buffer = reinterpret_cast<char*>(&a); //choice 2
Run Code Online (Sandbox Code Playgroud)

两者都很好.

//convert back
A *pA = static_cast<A*>(static_cast<void*>(buffer)); //choice 1
A *pA = reinterpret_cast<A*>(buffer); //choice 2
Run Code Online (Sandbox Code Playgroud)

即便这样工作正常!

那么,为什么我们reinterpret_cast在C++中有两个链接 static_cast可以完成它的工作呢?

你们中的一些人可能认为这个主题与之前的主题重复,例如本文底部列出的,但事实并非如此.这些主题讨论只在理论上,但他们没有给出甚至一个例子来展示为什么reintepret_cast是真正需要的,而2 static_cast肯定会失败.我同意,一个static_cast会失败.但两个怎么样?

如果两个链接的语法static_cast看起来很麻烦,那么我们可以编写一个函数模板,使其对程序员更友好:

template<class To, class From>
To any_cast(From v)
{
    return static_cast<To>(static_cast<void*>(v));
}
Run Code Online (Sandbox Code Playgroud)

然后我们可以使用它,如:

char *buffer = any_cast<char*>(&a); //choice 1
char *buffer = reinterpret_cast<char*>(&a); //choice 2

//convert back
A *pA = any_cast<A*>(buffer); //choice 1
A *pA = reinterpret_cast<A*>(buffer); //choice 2
Run Code Online (Sandbox Code Playgroud)

另外,请看这种any_cast有用的情况:正确转换fstream读写成员函数.

所以我的问题基本上是,

  • 为什么我们reinterpret_cast用C++?
  • 请告诉我一个单独的例子,其中两个链接 static_cast肯定不能做同样的工作?

Jam*_*lis 36

有些事情reinterpret_cast可以做到没有static_casts 序列可以做(所有来自C++ 03 5.2.10):

  • 指针可以显式转换为足以容纳它的任何整数类型.

  • 可以将整数类型或枚举类型的值显式转换为指针.

  • 指向函数的指针可以显式转换为指向不同类型函数的指针.

  • 类型"指针的构件的右值X类型的T1"可被显式转换为类型的右值"指针的构件Y类型的T2"如果T1T2都函数类型或两者的对象类型.

另外,来自C++ 03 9.2/17:

  • 指向POD结构对象的指针(适当地使用a转换)reinterpret_cast指向其初始成员(或者如果该成员是位字段,则指向它所驻留的单元),反之亦然.

  • 另外,作为第五个要点,指向POD结构的第一个元素的指针可以转换为指向结构的指针,反之亦然. (6认同)
  • @Nawaz:`int i = 42; char*p;`现在`p = static_cast <X>(static_cast <Y>(i));`将无法编译`X`和`Y`的所有可能值(除非它们是提供转换函数的类类型) . (3认同)

sha*_*oth 15

你需要reinterpret_cast得到一个带有硬编码地址的指针(就像这里):

int* pointer = reinterpret_cast<int*>( 0x1234 );
Run Code Online (Sandbox Code Playgroud)

您可能希望使用此类代码来访问某些内存映射设备输入输出端口.

  • @Nawaz:这完全回答了你的问题.在这种情况下,你的any_cast不起作用.你不能static_cast一个int到void*:"错误:从类型'int'无效static_cast到'void*'类型" (5认同)

Ton*_*roy 6

一个具体的例子:

char a[4] = "Hi\n";
char* p = &a;

f(reinterpret_cast<char (&)[4]>(p));  // call f after restoring full type
      // ^-- any_cast<> can't do this...

// e.g. given...
template <typename T, int N>   // <=--- can match this function
void f(T (&)[N]) { std::cout << "array size " << N << '\n'; }
Run Code Online (Sandbox Code Playgroud)


jco*_*der 5

除了其他人给出的实际原因之外,他们可以做的事情有所不同,因为它做了不同的工作是件好事.

static_cast说请将类型X的数据转换为Y. reinterpret_cast表示请将X中的数据解释为Y.

很可能底层操作是相同的,并且在许多情况下都可以工作.但是说请将X转换为Y并说"是的我知道这些数据被声明为X但请使用它就好像它真的是Y"之间存在概念上的区别.

  • +1 - 这在概念上是关键的,虽然有一些解决方法,例如给定`int x`你可以`reinterpret_cast <float&>(x)`,可以*不*`static_cast <float&>(x)`,但可以链接ala`*static_cast <float*>(static_cast <void*>(&x))`(注意any_cast不是一个干净的替代品:你需要一个额外的deref).至关重要的是,`static_cast <float>(x)`做了一些非常不同的事情:当值从`int`转换时舍入. (2认同)