【发布时间】:2014-02-06 08:53:33
【问题描述】:
在和某人争论他在this answer的评论线程中提出的建议时,我遇到了一些gcc4.8和VS2013拒绝编译但clang欣然接受并显示正确结果的代码。
#include <iostream>
int main()
{
int i{ 5 };
void* v = &i;
std::cout << reinterpret_cast<int&>(*v) << std::endl;
}
Live demo。 GCC 和 VC 都因我所期待的错误而失败,抱怨代码试图取消引用 reinterpret_cast 中的 void*。所以我决定在标准中查找这个。从 N3797,§5.2.10/11 [expr.reinterpret.cast]
如果类型“指向
T1”的表达式可以显式转换为类型“指向T2”的类型,则类型为T1的泛左值表达式可以转换为类型“引用T2”使用reinterpret_cast。结果引用与源 glvalue 相同的对象,但具有指定的类型。 [ 注意: 也就是说,对于左值,引用转换reinterpret_cast<T&>(x)与使用内置&和*运算符的转换*reinterpret_cast<T*>(&x)具有相同的效果(对于 @ 987654338@)。 —结束说明 ] 不创建临时文件,不制作副本,也不调用构造函数 (12.1) 或转换函数 (12.3)。
在这种情况下,T1 是 void,T2 是 int,void* 可以使用 reinterpret_cast 转换为 int*。所以所有的要求都满足了。
根据注释,reinterpret_cast<int&>(*v) 与*reinterpret_cast<int*>(&(*v)) 具有相同的效果,据我估计与*reinterpret_cast<int*>(v) 相同。
那么这是 GCC 和 VC 的错误,还是 clang 并且我以某种方式误解了这一点?
【问题讨论】:
-
如果您使用
void* v = &i; *v;会怎样?铿锵仍然没有抱怨。 Should I use static_cast or reinterpret_cast when casting a void* to whatever 看起来很有趣。 (警告:旧的,信息可能已经过时了。) -
根据this,看起来
&*ptr是合法的,但不等同于ptr(我猜这就是你在最后一个reinterpret_cast中的意思)。因此,指针仍然必须被取消引用。 -
@chris 在您链接到的问题的 cmets 中,C99 明确声明
&*E的 Oli Charlesworth says 与E相同。所以这部分确实成功了。我想剩下的问题是如果E是void,一个不完整的类型怎么办。 -
@Praetorian,是的,并且该注释仅在 C 中,而不是 C++。整个话题很混乱,但即使
void *p; &*p;是真正的noop,在C 中也应该可以正常工作。
标签: c++ reinterpret-cast