C++ 为什么我不能在 char * 和 unsigned char * 之间进行静态转换?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/10151834/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-27 13:40:15  来源:igfitidea点击:

Why can't I static_cast between char * and unsigned char *?

c++charreinterpret-caststatic-castunsigned-char

提问by Nick

Apparently the compiler considers them to be unrelated types and hence reinterpret_castis required. Why is this the rule?

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

采纳答案by EdChum

They are completely different types see standard:

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

3.9.1 Fundamental types [basic.fundamental]

1 Objects declared as characters char) shall be large enough to store any member of the implementation's basic character set. If a character from this set is stored in a character object, the integral value of that character object is equal to the value of the single character literal form of that character. It is implementation-defined whether a char object can hold negative values. Characters can be explicitly declared unsigned or
signed. Plain char, signed char, and unsigned char are three distinct types.A char, a signed char, and an unsigned char occupy the same amount of storage and have the same alignment requirements (basic.types); that is, they have the same object representation. For character types, all bits of the object
representation participate in the value representation. For unsigned character types, all possible bit patterns of the value representation represent numbers. These requirements do not hold for other types. In any particular implementation, a plain char object can take on either the same values as a signed char or an unsigned char; which one is implementation-defined.

3.9.1 基本类型[basic.fundamental]

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

So analogous to this is also why the following fails:

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

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

aand bare completely different types, really what you are questioning is why is static_cast so restrictive when it can perform the following without problem

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

and why can it not deduce that the target types are the same bit-field width and can be represented? It can do this for scalar types but for pointers, unless the target is derived from the source and you wish to perform a downcast then casting between pointers is not going to work.

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

Bjarne Stroustrop states why static_cast's are useful in this link: http://www.stroustrup.com/bs_faq2.html#static-castbut in abbreviated form it is for the user to state clearly what their intentions are and to give the compiler the opportunity to check that what you are intending can be achieved, since static_castdoes not support casting between different pointer types then the compiler can catch this error to alert the user and if they really want to do this conversion they then should use reinterpret_cast.

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

回答by Tobias Langner

you're trying to convert unrelated pointers with a static_cast. That's not what static_cast is for. Here you can see: Type Casting.

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

With static_cast you can convert numerical data (e.g. char to unsigned char should work) or pointer to related classes (related by some inheritance). This is both not the case. You want to convert one unrelated pointer to another so you have to use reinterpret_cast.

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

Basically what you are trying to do is for the compiler the same as trying to convert a char * to a void *.

基本上,您要为编译器做的事情与尝试将 char * 转换为 void * 相同。



Ok, here some additional thoughts why allowing this is fundamentally wrong. static_cast can be used to convert numerical types into each other. So it is perfectly legal to write the following:

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

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

what is also possible:

还有什么可能:

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

If you look at this code in assembler you'll see that the second cast is not a mere re-interpretation of the bit pattern of d but instead some assembler instructions for conversions are inserted here.

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

Now if we extend this behavior to arrays, the case where simply a different way of interpreting the bit pattern is sufficient, it might work. But what about casting arrays of doubles to arrays of ints? That's where you either have to declare that you simple want a re-interpretation of the bit patterns - there's a mechanism for that called reinterpret_cast, or you must do some extra work. As you can see simple extending the static_cast for pointer / arrays is not sufficient since it needs to behave similar to static_casting single values of the types. This sometimes needs extra code and it is not clearly definable how this should be done for arrays. In your case - stopping at \0 - because it's the convention? This is not sufficient for non-string cases (number). What will happen if the size of the data-type changes (e.g. int vs. double on x86-32bit)?

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

The behavior you want can't be properly defined for all use-cases that's why it's not in the C++ standard. Otherwise you would have to remember things like: "i can cast this type to the other as long as they are of type integer, have the same width and ...". This way it's totally clear - either they are related CLASSES - then you can cast the pointers, or they are numerical types - then you can cast the values.

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

回答by Michael Foukarakis

Aside from being pointers, unsigned char *and char *have nothing in common (EdChum already mentioned the fact that char, signed charand unsigned charare three different types). You could say the same thing for Foo *and Bar *pointer types to any dissimilar structures.

除了作为指针,unsigned char *char *没有什么共同点(EdChum已经提到的事实charsigned charunsigned char有三种不同类型)。你可能会说同样的事情Foo *Bar *指针类型的任何不同的结构。

static_castmeans that a pointer of the source type can be used as a pointer of the destination type, which requires a subtype relationship. Hence it cannot be used in the context of your question; what you need is either reinterpret_castwhich does exactly what you want or a C-style cast.

static_cast意味着源类型的指针可以作为目的类型的指针,这需要子类型关系。因此它不能用于您的问题的上下文中;您需要的是reinterpret_cast完全按照您的要求执行的操作或 C 风格的转换。