[英]Why do I Have to reinterpret_cast Pointer Pointers?
So this static_cast
code is totally legal: 所以这个static_cast
代码是完全合法的:
int n = 13;
void* pn = static_cast<void*>(&n);
void** ppn = &pn;
Yet this has to be made into a reinterpret_cast
to compile: 然而,必须将其转换为reinterpret_cast
以进行编译:
int n = 13;
int* foo = &n;
void** bar = static_cast<void**>(&foo);
If I don't change it I get the error: 如果我不改变它我得到错误:
error C2440:
static_cast
: cannot convert fromint **
tovoid **
note: Types pointed to are unrelated; 错误C2440:static_cast
:无法从int **
转换为void **
注意:指向的类型不相关; conversion requiresreinterpret_cast
, C-style cast or function-style cast 转换需要reinterpret_cast
,C风格的转换或函数式转换
So I take it the issue is "the types are unrelated". 所以我认为问题是“类型无关”。 Yet I still don't understand, if it's OK when going from an int*
to void*
how can they be unrelated as a int**
and a void**
? 然而我仍然不明白,如果从int*
到void*
是可以的void*
它们如何作为int**
和void**
无关?
int
is in no way related to void
. int
与void
无关。 The same goes for int**
and void**
and so they cannot be converted using static_cast
. 对于int**
和void**
也是如此,因此无法使用static_cast
进行转换。
void*
however, is special . void*
但是,很特别 。 Any data pointer type (including int*
) can be static_cast
into void*
and back, despite no type being related to void
(even further, the conversion to void*
doesn't need a cast, as it is implicit). 任何数据指针类型(包括int*
)都可以是static_cast
到void*
和back,尽管没有类型与void
相关(更进一步,转换为void*
不需要static_cast
转换,因为它是隐式的)。 int*
doesn't have this property, nor does void**
and nor does any other pointer besides void*
. int*
没有这个属性,也没有void**
,也没有除void*
之外的任何其他指针。
The additional freedoms that have been granted to void*
come with additional restrictions. 已授予void*
的额外自由带有额外限制。 void*
cannot be indirected, nor can it be used with pointer arithmetic. void*
不能被指向,也不能与指针算法一起使用。 These restrictions are only possible because there can never be an object of type void
. 这些限制是唯一可能的,因为永远不会有void
类型的对象。 Or from opposite point of view, objects of void
cannot exist because of these restrictions. 或者从相反的观点来看,由于这些限制, void
对象不可能存在。
void**
cannot be given those freedoms, because it cannot be given the same restrictions. void**
不能给予这些自由,因为它不能给予同样的限制。 It cannot be given those restrictions because void*
objects do exist and they need to exist. 它不能被赋予这些限制,因为void*
对象确实存在并且它们需要存在。 If we couldn't indirect or iterate void**
, then we couldn't use arrays of void*
for example. 如果我们不能间接或迭代void**
,那么我们就不能使用void*
数组。
void* pn = static_cast<void*>(&n);
is an implicit conversion; 是一种隐含的转换; you can also write 你也可以写
void *pn = &n;
It means that pn
stores a pointer to some object type; 这意味着pn
存储指向某个对象类型的指针; the programmer is responsible for knowing what that object type is. 程序员负责知道该对象类型是什么。 To cast back you need a static_cast
: 要回送你需要一个static_cast
:
int *pi = static_cast<int*>(pn);
Note that using static_cast
to cast to any type significantly different than the original ( float
is significantly different, const int
isn't) is a way of doing a reinterpretation. 请注意,使用static_cast
转换为与原始明显不同的任何类型( float
明显不同, const int
不是)是一种重新解释的方法。 You should spell that reinterpret_cast
not implicit conversion (or static_cast
) followed by static_cast
. 您应该拼写reinterpret_cast
不是隐式转换(或static_cast
),后跟static_cast
。
This is the whole purpose of void*
, an concept tracing back to C, where casts are spelled with C-style casts obviously (not static_cast
...) but have otherwise identical meanings. 这是void*
一个完整目的,一个追溯到C的概念,其中强制转换拼写为C风格的强制转换(不是static_cast
......),但具有相同的含义。
Going back to the syntax of declarations in C and C++: 回到C和C ++中的声明语法:
The declaration of a pointer to int
is int (*pi);
指向int
的指针是int (*pi);
(parentheses are useless but help illustrate the point), you can read it like: I declare that expression (*pi)
has type int
. (括号没用,但有助于说明这一点),你可以这样读:我声明表达式(*pi)
类型为int
。 You can read a function declaration that way: in int f(int i);
您可以通过以下方式读取函数声明:in int f(int i);
I declare that if i
has type int
then f(i)
has type int
. 我声明如果i
有int
类型,那么f(i)
类型为int
。
The declaration void (*pi);
声明void (*pi);
looks like a pointer to a void
but there is no such thing as an object of type void
, the expression *pi
isn't even well formed, it doesn't make sense. 看起来像是指向void
的指针,但是没有类型为void
的对象,表达式*pi
甚至没有很好地形成,它没有意义。 It's a special case in the type system: the syntax says "pointer to void", semantic says "pointer to something". 这是类型系统中的一个特例 :语法表示“指向void的指针”,语义表示“指向某事物的指针”。
In C and C++, a pointer object is a first class object and you can take its address and have a pointer to a pointer, etc. (Contrast with Java where references like other fundamental types aren't class objects.) 在C和C ++中,指针对象是第一个类对象,您可以获取其地址并指向指针等。(与Java对比,其中像其他基本类型的引用不是类对象。)
So you can have a int**
, int***
... pointers to (pointers ... to int
); 所以你可以有一个int**
, int***
...指向(指针...到int
); you can have for the same reason void**
: declared like a pointer to (pointer to void), semantically a pointer to (pointer to something). 你可以出于同样的原因void**
:声明为指向(指向void的指针),语义指向(指向某事物的指针)。
Just like a pointer to int
can't be assigned to a pointer to float
without a cast: 就像指向int
的指针一样,无法在没有强制转换的情况下指向float
的指针:
float *f = &i; // ill-formed
because of the type mismatch, a type different from void**
can't be assigned to a void**
: the result of dereferencing a void**
must be a void*
object . 由于类型不匹配,与void**
不同的类型不能分配给void**
: 取消引用void**
的结果必须是void*
对象 。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.