[英]Why do I Have to reinterpret_cast Pointer Pointers?
所以这个static_cast
代码是完全合法的:
int n = 13;
void* pn = static_cast<void*>(&n);
void** ppn = &pn;
然而,必须将其转换为reinterpret_cast
以进行编译:
int n = 13;
int* foo = &n;
void** bar = static_cast<void**>(&foo);
如果我不改变它我得到错误:
错误C2440:
static_cast
:无法从int **
转换为void **
注意:指向的类型不相关; 转换需要reinterpret_cast
,C风格的转换或函数式转换
所以我认为问题是“类型无关”。 然而我仍然不明白,如果从int*
到void*
是可以的void*
它们如何作为int**
和void**
无关?
int
与void
无关。 对于int**
和void**
也是如此,因此无法使用static_cast
进行转换。
void*
但是,很特别 。 任何数据指针类型(包括int*
)都可以是static_cast
到void*
和back,尽管没有类型与void
相关(更进一步,转换为void*
不需要static_cast
转换,因为它是隐式的)。 int*
没有这个属性,也没有void**
,也没有除void*
之外的任何其他指针。
已授予void*
的额外自由带有额外限制。 void*
不能被指向,也不能与指针算法一起使用。 这些限制是唯一可能的,因为永远不会有void
类型的对象。 或者从相反的观点来看,由于这些限制, void
对象不可能存在。
void**
不能给予这些自由,因为它不能给予同样的限制。 它不能被赋予这些限制,因为void*
对象确实存在并且它们需要存在。 如果我们不能间接或迭代void**
,那么我们就不能使用void*
数组。
void* pn = static_cast<void*>(&n);
是一种隐含的转换; 你也可以写
void *pn = &n;
这意味着pn
存储指向某个对象类型的指针; 程序员负责知道该对象类型是什么。 要回送你需要一个static_cast
:
int *pi = static_cast<int*>(pn);
请注意,使用static_cast
转换为与原始明显不同的任何类型( float
明显不同, const int
不是)是一种重新解释的方法。 您应该拼写reinterpret_cast
不是隐式转换(或static_cast
),后跟static_cast
。
这是void*
一个完整目的,一个追溯到C的概念,其中强制转换拼写为C风格的强制转换(不是static_cast
......),但具有相同的含义。
回到C和C ++中的声明语法:
指向int
的指针是int (*pi);
(括号没用,但有助于说明这一点),你可以这样读:我声明表达式(*pi)
类型为int
。 您可以通过以下方式读取函数声明:in int f(int i);
我声明如果i
有int
类型,那么f(i)
类型为int
。
声明void (*pi);
看起来像是指向void
的指针,但是没有类型为void
的对象,表达式*pi
甚至没有很好地形成,它没有意义。 这是类型系统中的一个特例 :语法表示“指向void的指针”,语义表示“指向某事物的指针”。
在C和C ++中,指针对象是第一个类对象,您可以获取其地址并指向指针等。(与Java对比,其中像其他基本类型的引用不是类对象。)
所以你可以有一个int**
, int***
...指向(指针...到int
); 你可以出于同样的原因void**
:声明为指向(指向void的指针),语义指向(指向某事物的指针)。
就像指向int
的指针一样,无法在没有强制转换的情况下指向float
的指针:
float *f = &i; // ill-formed
由于类型不匹配,与void**
不同的类型不能分配给void**
: 取消引用void**
的结果必须是void*
对象 。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.