简体   繁体   English

为什么我必须重新解释指针指针?

[英]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 from int ** to void ** note: Types pointed to are unrelated; 错误C2440: static_cast :无法从int **转换为void **注意:指向的类型不相关; conversion requires reinterpret_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 . intvoid无关。 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_castvoid*和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 . 我声明如果iint类型,那么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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM