在Microsoft VC2005和g ++编译器中,以下结果都会导致错误:
在win32 VC2005上: sizeof(wchar_t)是2
wchar_t *foo = 0;
static_cast<unsigned short *>(foo);
结果
error C2440: 'static_cast' : cannot convert from 'wchar_t *' to 'unsigned short *' ...
在Mac OS X或Linux上g ++: sizeof(wchar_t)为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到适当的整数类型是非法的。我确信有充分的理由......
答案 0 :(得分:6)
您无法在不相关的指针类型之间进行转换。指向的类型的大小是无关紧要的。考虑类型具有不同对齐要求的情况,允许这样的强制转换可能会在某些处理器上生成非法代码。指向不同类型的指针也可能具有不同的大小。这可能导致您获得的指针无效或指向完全不同的位置。如果你知道你的程序编译器arch和os你可以侥幸逃脱,那么Reinterpret_cast是你所遇到的逃脱舱口之一。
答案 1 :(得分:4)
与char
一样,wchar_t
的签名未由标准定义。把它与非2的补码整数的可能性放在一起,并且wchar_t
值为c
,
*reinterpret_cast<unsigned short *>(&c)
可能不等于:
static_cast<unsigned short>(c)
在第二种情况下,在wchar_t
是符号+幅度或1的补码类型的实现中,c的任何负值都使用模2 ^ N转换为无符号,这会改变位。在前一种情况下,位模式被拾取并按原样使用(如果它完全有效)。
现在,如果结果不同,那么实现在指针类型之间提供static_cast
没有现实的方法。它能做什么,在unsigned short*
指针上设置一个标志,说“顺便说一句,当你加载它时,你还必须进行符号转换”,然后在所有未签名的短载荷上检查这个标志?
这就是为什么通常不能在指向不同整数类型的指针之间进行转换,并且我认为这不安全是为什么它们之间没有通过static_cast进行转换的原因。
如果您要转换的类型恰好是wchar_t的所谓“底层类型”,那么生成的代码几乎肯定可以用于实现,但是不可移植。所以标准没有提供一个特殊情况,允许你只为那种类型的static_cast,大概是因为它会隐藏可移植代码中的错误。如果您知道reinterpret_cast是安全的,那么您可以使用它。不可否认,在编译时使用一种简单的方法断言它是安全的会很好,但就标准而言,你应该围绕它进行设计,因为即使取消引用reinterpret_cast
也不需要实现。 ed指针没有崩溃。
答案 2 :(得分:2)
通过使用由可缩小类型限制的static_cast的规范,例如:std :: ostream&amp;到std :: ofstream&amp;。事实上,wchar_t只是扩展但广泛使用。 你的情况(如果你真的需要它)应该由reinterpret_cast
修复顺便说一句,MSVC ++有一个选项 - 将wchar_t视为宏(短)或作为独立数据类型。
答案 3 :(得分:1)
指针不是魔术“没有限制,任何事情都有”工具。
根据语言规范它们实际上是非常有限的。它们不允许您绕过类型系统或C ++语言的其余部分,这是您正在尝试做的事情。
你试图告诉编译器“假装你之前存储在这个地址的wchar_t
实际上是一个int。现在读一下。”
这没有意义。存储在该地址的对象是wchar_t
,没有别的。您正在使用静态类型语言,这意味着每个对象都有一个,并且juts one,键入。
如果你愿意徘徊于实现定义的行为领域,你可以使用reinterpret_cast告诉编译器只是假装它没问题,并按照它认为合适的方式解释结果 。但是结果并没有由标准规定,而是由实施确定。
如果没有那个演员,这个操作毫无意义。 wchar_t
不是int
或short
。