WinAPI LPWSTR,C++11 u16string?

Posted

技术标签:

【中文标题】WinAPI LPWSTR,C++11 u16string?【英文标题】:WinAPI LPWSTR, C++11 u16string? 【发布时间】:2012-08-24 00:07:23 【问题描述】:

如果我正在为 Windows 开发并且某些 WinAPI 函数要求我使用 LPWSTR 作为字符串数据类型。在我的库中使用 C++11 的 u16string 可以吗?这两种数据类型是一样的吗?

LPWSTR 看起来更像是 wchar_t,但是已经没有人喜欢 wchar_t了...

【问题讨论】:

"没有人喜欢 wchar_t..." Windows 上没有人对wchar_t 有问题,是有 4 字节的人wchar_t 不喜欢它。 :-P 我不喜欢 wchar_t。我有 16 个字节。它仍然小于一个字符。我认为你不应该使用 char16_t 或 wchar_t。 utf8everywhere.org 总结了我的观点。 @ildjarn:我在 Windows 上,我遇到 wchar_t 有问题。窄字符 + UTF-8 是我要走的路! 【参考方案1】:

C++11 char16_t 类型不同于 wchar_t。理论上,您可以在 char16_t* 和 Windows 的 wchar_t* 之间选择 reinterpret_cast(Windows 的 wchar_t 是 16 位)。然而,在实践中,Visual C++ 10.0——我认为也是 Visual C++ 11.0——缺乏对像 u'A'u"A" 这样的 Unicode 文字的支持。

总结(我发现在 SO 上最好明确所有结论):

“可以在我的库中使用 C++11 的 u16string 吗?”当然可以,但不能作为 wchar_t 字符串的直接插件替代品,并且截至 2012 年目前存在问题(由于缺乏对文字的支持)如果您计划支持 Visual C++。

“这两种数据类型是一样的吗?”不是。

“没有人喜欢 wchar_t 了...”当然不是这样。

【讨论】:

所以最后最好还是坚持使用 TCHAR(或者 WCHAR,如果你不再支持 Win 9.x)并且根本不使用新的 C++11 Unicode 支持?跨度> @user1400869:我建议只使用wchar_t。除了其他优点之外,它在代码中也没有那么碍眼。但从技术上讲,定义一个依赖于平台的编码值类型是可行的,它将映射到 Windows 中的wchar_t。在我看来,使用这种类型更符合 C++ 的精神(考虑其他依赖于平台的类型,例如 int)。但是建立必要的基础设施需要做大量的工作。所以,wchar_t。 :-)【参考方案2】:

wchar_tchar16_t 是不同的类型,因此不能将u16string.c_str() 用作LPWSTR(没有reinterpret_cast 会导致未定义的行为)。

如果您确信在您的平台上 wchar_t 被编码为 UTF-16,您可以复制以下数据:

std::wstring my_wstring(my_u16string.begin(), my_u16string.end());

然后使用my_wstring.c_str() 作为 LPWSTR。在函数调用中,你可以使用一个临时的:

SomeWindowsAPI(std::wstring(my_u16string.begin(), my_u16string.end()).c_str());

【讨论】:

在特定平台时无需复制。 @Cheersandhth.-虽然它们是不同的类型,但不需要实现确保通过强制转换指针读取与通过原始指针读取具有相同的值。 编译器是平台的一部分。如果您使用的编译器在这方面有很多问题(阅读:g++),那么您必须使用编译器特定的解决方案来解决编译器的问题。就这样。该标准没有特定于平台的保证。编译器会。 我不确定我是否理解。当您可以首先编写可与任何编译器(包括 Intel、clang 等)一起使用的一致代码时,为什么还要编写特定于 g++ 的代码? @RemyLebeau 我同意这可行,但这是未定义的行为(指针别名),足够聪明的优化器可能会破坏它。【参考方案3】:

Windows 上的wchar_t 是 16 位的,LPWSTR 值是 UTF-16 编码的,所以是的,您可以在与 API 交互时使用 char16_tu16string 值,尽管您必须进行类型转换让编译器满意。

【讨论】:

从技术上讲,类型转换会导致 UB,所以我会说这里的答案是“不”,而不是“是”。 @ildjarn:对于特定于 Windows 的代码,转换由编译器定义。这就是reinterpret_cast @RemyLebeau 这是严格的别名规则。您不能通过不同类型的对象访问对象的值(有一些例外,例如 char)。参见 [basic.lval] 3.10/10。 “如果程序试图通过非下列类型之一的左值访问对象的存储值,则行为未定义:” @Cheersandhth.-Alf 我不明白为什么在相同大小的不相关整数类型之间进行转换不会违反严格的别名。这属于哪些要点?另外我不确定您指的是 g++ 的哪种行为。 @Cheersandhth.-Alf wchar_t 没有任何相应的有符号或无符号类型(相应的类型在第 3.9.1 节中讨论)。我相信通过短类型的 glvalue 访问 wchar_t 对象在技术上是未定义的行为。仅仅因为某些东西有效并不意味着它实际上已经很好地定义了。例如,将 n 个整数的数组作为 2n 个短裤的数组访问肯定是在严格别名下的 UB,但它在许多实现上都可以正常工作。

以上是关于WinAPI LPWSTR,C++11 u16string?的主要内容,如果未能解决你的问题,请参考以下文章

在 C++17 / C++20 中从 wstring 转换为 u16string 并返回(标准符合)

怎么把char型数组转换为lpwstr

移动窗口时 C++/WinApi 内存使用率上升

如何使用 C WinAPI 获取当前麦克风输入电平?

C++ WinAPI - GetConsoleScreenBufferInfo 总是因句柄无效而失败(返回 0)

C++ , winapi 比较两个 WCHAR * 字符串