static_cast wchar_t* 为 int* 或 Short* - 为什么它是非法的?
在 Microsoft VC2005 和 g++ 编译器中,以下结果会导致错误:
On win32 VC2005: sizeof(wchar_t) is 2
wchar_t *foo = 0;
static_cast<unsigned short *>(foo);
结果
error C2440: 'static_cast' : cannot convert from 'wchar_t *' to 'unsigned short *' ...
On Mac OS X 或 Linux g++: sizeof(wchar_t) is 4
wchar_t *foo = 0;
static_cast<unsigned int *>(foo);
结果当然
error: invalid static_cast from type 'wchar_t*' to type 'unsigned int*'
,我总是可以使用reinterpret_cast。 但是,我想了解为什么编译器认为将 static_cast 转换为适当的整数类型是非法的。 我确信有一个充分的理由......
In both Microsoft VC2005 and g++ compilers, the following results in an error:
On win32 VC2005: sizeof(wchar_t) is 2
wchar_t *foo = 0;
static_cast<unsigned short *>(foo);
Results in
error C2440: 'static_cast' : cannot convert from 'wchar_t *' to 'unsigned short *' ...
On Mac OS X or Linux g++: sizeof(wchar_t) is 4
wchar_t *foo = 0;
static_cast<unsigned int *>(foo);
Results in
error: invalid static_cast from type 'wchar_t*' to type 'unsigned int*'
Of course, I can always use reinterpret_cast. However, I would like to understand why it is deemed illegal by the compiler to static_cast to the appropriate integer type. I'm sure there is a good reason...
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
通过规范使用受窄类型限制的 static_cast,例如: std::ostream& 到 std::ofstream&。 事实上wchar_t只是扩展但被广泛使用。
你的情况(如果你真的需要它)应该由reinterpret_cast修复
顺便说一下,MSVC++有一个选项 - 将 wchar_t 视为宏(短)或独立数据类型。
By spec using of static_cast restricted by narrowable types, eg: std::ostream& to std::ofstream&. In fact wchar_t is just extension but widely used.
Your case (if you really need it) should be fixed by reinterpret_cast
By the way MSVC++ has an option - either treat wchar_t as macro (short) or as stand-alone datatype.
指针并不是神奇的“没有限制,一切皆可”的工具。
实际上,它们受到语言规范的很大限制。 它们不允许您绕过类型系统或 C++ 语言的其余部分,而这正是您想要做的。
您试图告诉编译器“假装您之前存储在该地址的
wchar_t
实际上是一个 int。现在读取它。”那没有意义。 存储在该地址的对象是
wchar_t
,仅此而已。 您正在使用静态类型语言,这意味着每个对象都有一种类型,并且只有一种类型。如果您愿意进入实现定义的行为领域,您可以使用reinterpret_cast 告诉编译器假装一切正常,并按照它认为合适的方式解释结果。 但结果不是由标准规定的,而是由实施规定的。
如果没有这个演员,操作就毫无意义。
wchar_t
不是int
或short
。Pointers are not magic "no limitations, anything goes" tools.
They are, by the language specification actually very constrained. They do not allow you to bypass the type system or the rest of the C++ language, which is what you're trying to do.
You are trying to tell the compiler to "pretend that the
wchar_t
you stored at this address earlier is actually an int. Now read it."That does not make sense. The object stored at that address is a
wchar_t
, and nothing else. You are working in a statically typed language, which means that every object has one, and juts one, type.If you're willing to wander into implementation-defined behavior-land, you can use a reinterpret_cast to tell the compiler to just pretend it's ok, and interpret the result as it sees fit. But then the result is not specified by the standard, but by the implementation.
Without that cast, the operation is meaningless. A
wchar_t
is not anint
or ashort
.您不能在不相关的指针类型之间进行转换。 所指向的类型的大小无关紧要。 考虑类型具有不同对齐要求的情况,允许这样的强制转换可能会在某些处理器上生成非法代码。 指向不同类型的指针也可能具有不同的大小。 这可能会导致您获得的指针无效或指向完全不同的位置。 如果您知道您的程序编译器架构和操作系统可以摆脱它,那么 Reinterpret_cast 就是您所拥有的逃生舱口之一。
You cannot cast between unrelated pointer types. The size of the type pointed to is irrelevant. Consider the case where the types have different alignment requirements, allowing a cast like this could generate illegal code on some processesors. It is also possible for pointers to different types to have differrent sizes. This could result in the pointer you obtain being invalid and or pointing at an entirely different location. Reinterpret_cast is one of the escape hatches you hacve if you know for your program compiler arch and os you can get away with it.
与
char
一样,wchar_t
的符号不是由标准定义的。 将其与非 2 的补码整数的可能性放在一起,对于wchar_t
值c
,可能不等于:
在第二种情况下,在实现中
wchar_t
是符号+幅度或 1 的补码类型,c 的任何负值都会使用模 2^N 转换为无符号,这会更改位。 在前一种情况下,位模式被拾取并按原样使用(如果它有效的话)。现在,如果结果不同,那么实现就没有实际的方法来在指针类型之间提供
static_cast
。 它能做什么,在unsigned Short*
指针上设置一个标志,说“顺便说一句,当你从这里加载时,你还必须进行符号转换”,然后检查这个标志所有未签名的短负载?这就是为什么一般来说,在指向不同整数类型的指针之间进行转换是不安全的,并且我相信这种不安全性就是为什么它们之间没有通过 static_cast 进行转换的原因。
如果您要转换的类型恰好是 wchar_t 的所谓“底层类型”,那么生成的代码几乎肯定可以用于实现,但不可移植。 因此,该标准没有提供特殊情况,允许您仅针对该类型进行 static_cast ,大概是因为它会隐藏可移植代码中的错误。 如果你知道reinterpret_cast是安全的,那么你就可以使用它。 诚然,如果能有一种直接的方法在编译时断言它是安全的,那就太好了,但就标准而言,您应该围绕它进行设计,因为即使取消引用reinterpret_cast<,也不需要实现/code>ed 指针不会崩溃。
As with
char
, the signedness ofwchar_t
is not defined by the standard. Put this together with the possibility of non-2's complement integers, and for for awchar_t
valuec
,may not equal:
In the second case, on implementations where
wchar_t
is a sign+magnitude or 1's complement type, any negative value of c is converted to unsigned using modulo 2^N, which changes the bits. In the former case the bit pattern is picked up and used as-is (if it works at all).Now, if the results are different, then there's no realistic way for the implementation to provide a
static_cast
between the pointer types. What could it do, set a flag on theunsigned short*
pointer, saying "by the way, when you load from this, you have to also do a sign conversion", and then check this flag on all unsigned short loads?That's why it's not, in general, safe to cast between pointers to distinct integer types, and I believe this unsafety is why there is no conversion via static_cast between them.
If the type you're casting to happens to be the so-called "underlying type" of wchar_t, then the resulting code would almost certainly be OK for the implementation, but would not be portable. So the standard doesn't offer a special case allowing you a static_cast just for that type, presumably because it would conceal errors in portable code. If you know reinterpret_cast is safe, then you can just use it. Admittedly, it would be nice to have a straightforward way of asserting at compile time that it is safe, but as far as the standard is concerned you should design around it, since the implementation is not required even to dereference a
reinterpret_cast
ed pointer without crashing.