显然,编译器认为它们是不相关的类型,因此需要reinterpret_cast
。为什么这是规则?
答案 0 :(得分:30)
它们是完全不同的类型,请参阅标准:
3.9.1基本类型[basic.fundamental]
1声明为字符char的对象应足够大 存储实现的基本字符集的任何成员。如果一个 这个集合中的字符存储在一个字符对象中,即积分 该字符对象的值等于单个值的值 该角色的字符文字形式。它是 实现 - 定义char对象是否可以保持负数 值。字符可以显式声明为unsigned或
签。 Plain char,signed char和unsigned char 三种不同的类型。 一个char,一个signed char和一个unsigned char 占用相同的存储量并具有相同的对齐方式 要求( basic.types );也就是说,它们具有相同的对象 表示。对于字符类型,对象的所有位
代表参与价值表示。对于未签名 字符类型,值表示的所有可能的位模式 代表数字。这些要求不适用于其他类型。在 任何特定的实现,一个普通的char对象都可以采取 与signed char或unsigned 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
在这个链接中有用的原因:http://www.stroustrup.com/bs_faq2.html#static-cast但是缩写形式是用户清楚地说明他们的意图是什么,并让编译器有机会检查由于static_cast
不支持在不同指针类型之间进行转换,因此编译器可以捕获此错误以提醒用户,如果他们真的想要进行此转换,那么他们应该使用{{1 }}
答案 1 :(得分:8)
你试图用static_cast转换不相关的指针。这不是static_cast的用途。您可以在此处看到:Type 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 - 因为它是惯例?这对于非字符串情况(数字)来说是不够的。如果数据类型的大小发生变化(例如x86-32bit上的int与double)会发生什么?
无法为所有用例正确定义所需的行为,这就是为什么它不符合C ++标准的原因。否则你将不得不记住这样的事情:“我可以将这种类型转换为另一种类型,只要它们是整数类型,具有相同的宽度和......”。这种方式非常清楚 - 要么它们是相关的CLASSES - 然后你可以转换指针,或者它们是数字类型 - 那么你可以转换值。
答案 2 :(得分:4)
除了指点之外,unsigned char *
和char *
没有任何共同之处(EdChum已经提到char
,signed char
和unsigned char
三种不同的事实类型)。您可以对Foo *
和Bar *
指针类型对任何不同的结构说同样的事情。
static_cast
表示源类型的指针可以用作目标类型的指针,这需要子类型关系。因此,它不能用于你的问题;你需要的是reinterpret_cast
,它可以完全符合你的要求,也可以是C风格的演员。