56

显然编译器认为它们是不相关的类型,因此reinterpret_cast是必需的。为什么这是规则?

4

3 回答 3

44

它们是完全不同的类型,见标准:

3.9.1 基本类型[basic.fundamental]

1 声明为字符 char) 的对象应足够大以存储实现的基本字符集的任何成员。如果该集合中的字符存储在字符对象中,则该字符对象的整数值等于该字符的单个字符文字形式的值。char 对象是否可以保存负值是实现定义的。字符可以显式声明为无符号或有
符号。 普通字符、有符号字符和无符号字符是三种不同的类型。 char、signed char 和 unsigned char 占用相同的存储量并具有相同的对齐要求(basic.types); 也就是说,它们具有相同的对象表示。对于字符类型,对象表示的所有位都
参与值表示。对于无符号字符类型,值表示的所有可能的位模式都表示数字。这些要求不适用于其他类型。在任何特定实现中,普通 char 对象可以采用与带符号字符或无符号字符相同的值;哪一个是实现定义的。

与此类似也是以下失败的原因:

unsigned int* a = new unsigned int(10);
int* b = static_cast<int*>(a); // error different types

a并且b是完全不同的类型,您真正要问的是为什么 static_cast 在可以毫无问题地执行以下操作时如此受限制

unsigned int a = new unsigned int(10);
int b = static_cast<int>(a); // OK but may result in loss of precision

为什么不能推断出目标类型是相同的位域宽度并且可以表示?它可以对标量类型但对指针执行此操作,除非目标是从源派生的并且您希望执行向下转换,然后指针之间的转换将不起作用。

Bjarne Stroustrop 说明了为什么static_cast's 在此链接中很有用:http: //www.stroustrup.com/bs_faq2.html#static-cast但以缩写形式,用户可以清楚地说明他们的意图并给编译器有机会检查您的意图是否可以实现,因为static_cast不支持不同指针类型之间的转换,所以编译器可以捕获此错误以提醒用户,如果他们真的想要进行此转换,则应使用reinterpret_cast.

于 2012-04-14T08:26:34.850 回答
8

您正在尝试使用 static_cast 转换不相关的指针。这不是 static_cast 的用途。在这里你可以看到:类型 Casting

使用 static_cast 您可以转换数字数据(例如 char 到 unsigned char 应该可以工作)或指向相关类的指针(通过某些继承相关)。这两种情况都不是。您想将一个不相关的指针转换为另一个,因此您必须使用 reinterpret_cast。

基本上,您尝试对编译器执行的操作与尝试将 char * 转换为 void * 相同。


好的,这里有一些额外的想法,为什么允许这样做从根本上是错误的。static_cast 可用于将数字类型相互转换。因此,编写以下内容是完全合法的:

char x = 5;
unsigned char y = static_cast<unsigned char>(x);

还有什么可能:

double d = 1.2;
int i = static_cast<int>(d);

如果您在汇编程序中查看此代码,您会发现第二次转换不仅仅是对 d 位模式的重新解释,而是在此处插入了一些用于转换的汇编程序指令。

现在,如果我们将这种行为扩展到数组,只需一种不同的方式来解释位模式就足够了,它可能会起作用。但是如何将双精度数组转换为整数数组呢?这就是您必须声明您想要重新解释位模式的地方 - 有一种称为 reinterpret_cast 的机制,或者您必须做一些额外的工作。正如您所看到的,简单地为指针/数组扩展 static_cast 是不够的,因为它需要表现得类似于 static_casting 类型的单个值。这有时需要额外的代码,并且不清楚如何为数组完成此操作。在你的情况下 - 停在 \0 - 因为这是惯例?这对于非字符串情况(数字)是不够的。如果数据类型的大小发生变化(例如 int vs.

无法为所有用例正确定义您想要的行为,这就是它不在 C++ 标准中的原因。否则,您将不得不记住以下内容:“我可以将这种类型转换为另一种类型,只要它们是整数类型,具有相同的宽度并且......”。这样就很清楚了-它们是相关的类-然后您可以转换指针,或者它们是数字类型-然后您可以转换值。

于 2012-04-14T07:45:52.300 回答
4

除了是指针,unsigned char *andchar *没有任何共同点(EdChum 已经提到char,signed charunsigned char是三种不同的类型)。您可以对任何不同结构的指针类型Foo *说同样的话。Bar *

static_cast表示源类型的指针可以作为目的类型的指针,需要有子类型关系。因此,它不能在您的问题的上下文中使用;您需要的是reinterpret_cast完全符合您的要求或 C 风格的演员表。

于 2012-04-14T10:31:03.663 回答