4

在 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 转换为适当的整数类型是非法的。我敢肯定有一个很好的理由...

4

4 回答 4

6

您不能在不相关的指针类型之间进行转换。指向的类型的大小无关紧要。考虑类型具有不同对齐要求的情况,允许这样的强制转换可能会在某些处理器上生成非法代码。指向不同类型的指针也可能具有不同的大小。这可能会导致您获得的指针无效或指向完全不同的位置。如果您知道程序编译器架构和操作系统,那么 Reinterpret_cast 是您拥有的逃生舱之一,您可以摆脱它。

于 2009-08-06T13:02:14.587 回答
4

char一样,wchar_t标准没有定义 的符号。将其与非 2 补码整数的可能性放在一起,对于一个wchar_tc

*reinterpret_cast<unsigned short *>(&c)

可能不等于:

static_cast<unsigned short>(c)

在第二种情况下,在wchar_t符号+幅度或 1 的补码类型的实现中,c 的任何负值都使用模 2^N 转换为无符号数,这会更改位。在前一种情况下,位模式被拾取并按原样使用(如果它确实有效)。

现在,如果结果不同,那么实现就没有现实的方法来提供static_cast指针类型之间的 a。它可以做什么,在unsigned short*指针上设置一个标志,说“顺便说一下,当你从这里加载时,你还必须做一个符号转换”,然后在所有无符号短负载上检查这个标志?

这就是为什么在指向不同整数类型的指针之间转换通常不安全的原因,我相信这种不安全性是为什么它们之间没有通过 static_cast 进行转换的原因。

如果您要转换的类型恰好是 wchar_t 的所谓“基础类型”,那么生成的代码几乎肯定可以用于实现,但不能移植。因此,该标准没有提供一个特殊情况,允许您仅针对该类型使用 static_cast,大概是因为它会隐藏可移植代码中的错误。如果您知道 reinterpret_cast 是安全的,那么您可以使用它。诚然,最好有一种在编译时断言它是安全的直接方法,但就标准而言,您应该围绕它进行设计,因为即使取消引用reinterpret_casted 指针也不需要实现而不崩溃。

于 2009-08-06T13:14:28.740 回答
2

通过规范使用受窄类型限制的 static_cast,例如:std::ostream& 到 std::ofstream&。事实上 wchar_t 只是扩展但被广泛使用。你的情况(如果你真的需要的话)应该由 reinterpret_cast 修复

顺便说一句,MSVC++ 有一个选项 - 将 wchar_t 视为宏(短)或独立数据类型。

于 2009-08-06T12:47:11.737 回答
1

指针不是神奇的“没有限制,一切顺利”的工具。

它们实际上受到语言规范的限制。它们不允许您绕过类型系统或 C++ 语言的其余部分,而这正是您想要做的。

您试图告诉编译器“假装wchar_t您之前存储在此地址的实际是一个 int。现在阅读它。”

那没有意义。存储在该地址的对象是 a wchar_t,仅此而已。您正在使用一种静态类型的语言,这意味着每个对象都有一个并且只有一个类型。

如果您愿意漫游到实现定义的行为领域,您可以使用 reinterpret_cast 告诉编译器只是假装没问题,并按照它认为合适的方式解释结果。但是结果不是标准规定的,而是实施规定的。

没有那个演员表,手术就毫无意义。Awchar_t不是 aint或 a short

于 2009-08-06T15:21:27.450 回答