为什么我不能在char *和unsigned char *之间进行static_cast?

时间:2012-04-14 07:21:56

标签: c++ char reinterpret-cast static-cast unsigned-char

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

3 个答案:

答案 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

ab是完全不同的类型,你真正在质疑的是为什么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已经提到charsigned charunsigned char三种不同的事实类型)。您可以对Foo *Bar *指针类型对任何不同的结构说同样的事情。

static_cast表示源类型的指针可以用作目标类型的指针,这需要子类型关系。因此,它不能用于你的问题;你需要的是reinterpret_cast,它可以完全符合你的要求,也可以是C风格的演员。