为什么这个角色转换不起作用?



Visual Studio 2008

项目编译为多字节字符集

LPWSTR lpName[1] = {(WCHAR*)_T("Setup")};

转换后,lpName[0]包含垃圾(至少在VS中预览时)

LPWSTR的类型定义如下:
typedef __nullterminated WCHAR *NWPSTR, *LPWSTR, *PWSTR;

这是我上面评论的扩展版本。

显示的代码将类型a的指针强制转换为类型B的指针。这是一个低级别的、依赖于机器的操作。它几乎从不起将类型a的对象转换为类型B的对象的作用,尤其是如果一种类型是正则字符类型,而另一种是宽字符类型。

想象一下,你拿着一本法语书,大声读,就好像它是用英语写的一样。

FRENCH* book;
readaloud ((ENGLISH*) book);

你听到的大多是胡言乱语。这两种语言中使用的字母是相同的(或相似的,无论如何),但两种语言的规则完全不同。两种语言的表达方式相同,但意义不同。

这与我们这里的非常相似。无论你有什么类型,比特和字节都是一样的,但规则完全不同。您可以根据常规字符规则排列位,并尝试根据宽字符规则对其进行解释。它不起作用。这两种情况下的表述是相同的,但含义不同。

要将一种字符类型转换为另一种,通常需要一个查找表或其他方法将每个字符从一种类型转换为其他类型——更改表示,但保留其含义。同样,要把一本法语书转换成英语书,你需要使用一个大的查找表,也就是字典。。。好吧,这里的类比打破了,因为没有一套正式的转换规则,你需要有创造性!但你明白了。

C++的规则实际上禁止这样的强制转换。只能将对象类型poiner强制转换为void*,并且只能使用结果将其强制转换回原始对象类型。其他一切都是否定的(除非你愿意冒险进入未定义行为的领域)。

那么你该怎么办呢?

  1. 选择一个字符变体并坚持使用
  2. 如果必须在不同风格之间进行转换,请使用库函数进行转换
  3. 尽量避免指针强制转换,它们几乎总是表示出现问题

我想你要找的是

LPTSTR lpName[1] = {_T("Setup")};

带有T的各种typedef(例如TSTRLPTSTR)取决于您使用的是unicode还是多字节或其他任何类型。通过使用这些,您应该能够编写以您正在使用的任何编码工作的代码(即,明天您可以切换到ascii,并且您的大部分代码应该仍然可以工作)。

编辑

如果您确实需要在编码之间进行转换,那么可以使用各种转换函数,例如wcstombs(或微软的文档)和mbstowcs。这些在<cstdlib> 中定义