int i = 1000;
void *p = &i;
int *x = static_cast<int*>(p);
int *y = reinterpret_cast<int*>(p);
将 void*
转换为 int*
应该使用哪种强制转换?为什么?
static_cast
提供了一种方法,可以在你的程序设计中知道指向的东西确实是一个int
时进行转换。
static_cast
的设计目的是用于反转任何隐式转换。由于您隐式地转换为void*
,因此如果您知道您真的只是要反转以前的转换,则可以(并且应该)使用static_cast
进行转换。
在这种假设下,没有任何被重新解释的东西-void
是不完整的类型,意味着它没有值,因此在任何时候,您都不会将存储的int值“视为void”或将存储的“void值”视为int。void*
只是一种丑陋的方式,表示“我不知道类型,但我将把指针传递给其他人来处理”。
reinterpret_cast
如果您省略了细节,这些细节意味着您可能实际上正在使用与编写时不同的类型读取内存,并且请注意,您的代码的可移植性有限。
顺便说一下,在C ++中以这种方式使用void*
指针的好理由并不多。 C样式的回调接口通常可以用模板函数(对于类似标准函数qsort
的任何内容)或虚拟接口(对于类似已注册侦听器的任何内容)来替换。如果您的C++代码正在使用某个C API,则当然没有太多选择。
reinterpret_cast
,因此将是特定于实现的。在某些实现中,int
的对齐要求为1,因此不会出现此问题。在另一种可能导致指针错位的实现中,相同的代码将超出其“有限的可移植性”。在另一种实现中,由于严格的别名规则,您根本无法进行类型游戏(除了char)。 - Steve Jessop在当前的C++中,你不能像那段代码一样使用reinterpret_cast
。对于将void*
转换为int*
,你只能使用static_cast
(或等效的C风格转换)。
对于不同函数类型指针或不同对象类型指针之间的转换,需要使用reinterpret_cast
。
在C++0x中,reinterpret_cast<int*>(p)
将等同于static_cast<int*>(p)
。它可能会被纳入下一个WPs之一。
有一个误解,认为reinterpret_cast<T*>(p)
会将p
的位解释为表示T*
的位。在这种情况下,它将使用p
的类型读取p
的值,然后将该值转换为T*
。实际上,只有当您将其强制转换为引用类型时,才会发生直接使用类型T*
的表示形式读取p
的位的类型游戏,例如reinterpret_cast<T*&>(p)
。
据我所知,所有当前编译器都允许从void*
进行reinterpret_cast
,并且行为等同于相应的static_cast
,即使在当前的C++03中不允许。如果拒绝它,将破坏大量代码,这样做没有任何动力。
static_cast
和reinterpret_cast
转换T* -> void* -> T保证产生原始值。由于这必须对每个指针值都成立,为了防止它,一个反常的编译器必须记录一些系统性的无谓更改,比如从void进行reinterpret_cast时添加1,反之亦然。没有人会相信这种说法。 - Cheers and hth. - Alfvoid
不是一个对象类型。为什么 5.2.10/1 与 9.2/17 相矛盾? - Johannes Schaub - litbp
的赋值,例如从指向比int
小的东西的指针进行赋值,那么static_cast
肯定也会允许同样奇怪的行为。我认为使用static_cast
的原因是为了传达转换的意图(即它不应该重新解释),但是转换本身并不能防止重新解释的发生,因为void*
可以转换为任何对象指针类型,并且可以从任何对象指针类型转换。 - Steve Jessop
void *
作为开始。 - Jerry Coffin