wchar_t 和 char16_t 在 Windows 上是一样的吗?

Posted

技术标签:

【中文标题】wchar_t 和 char16_t 在 Windows 上是一样的吗?【英文标题】:Are wchar_t and char16_t the same thing on Windows? 【发布时间】:2019-04-17 00:05:19 【问题描述】:

我有一个std::u16string 的实例,我可以将它的c_str() 传递给需要LPCWSTR 的Win32 API,而无需任何类型的转换吗?例如,我可以安全地这样做吗:

auto u16s = std::u16string(u"Hello");
::SetWindowTextW(hWnd, reinterpret_cast<LPCWSTR>(u16s.c_str()));    

更新,MSDN 说 here wchar_t 是 UTF-16LE,而 char16_t 只是 UTF-16,没有指定字节序。是否可以安全地假设 char16_t 在 Windows 上也始终是 UTF-16LE?或者那是特定于 MSVC 编译器的,因此如果我使用 GCC 编译,它可能是 UTF-32LE(或者可能是 UTF-16BE)?

【问题讨论】:

这将完全取决于工具链中使用的 C++ 编译器 - 通常是 Visual C++ 的某个版本,因为您通常将 Windows SDK 与 Visual Studio 捆绑在一起。但是可以使用带有 Windows SDK 的 GCC 和 MINGW 编译器(Code::Blocks 等),在这种情况下,您需要更加小心严格区分 Windows 类型(WCHAR、TCHAR、INT)和编译器类型( wchar_t、std::*、int32_t 等)以及特定编译器所做的任何事情。 【参考方案1】:

是的。 WCHAR strings on Windows are UTF-16.

【讨论】:

Here MSDN 说 wchar_t 是 UTF-16LE,而 char16_t 是 UTF-16。这是否意味着 UTF-16LE 与 UTF-16 是一回事? UTF-16LE 中的“LE”表示“小端”。您使用的所有现代处理器(您会发现 Windows 处理器)几乎肯定会是小端,因此实际上 UTF-16 与 Windows 上的 UTF-16LE 相同。 那么说char16_t 在Windows 上总是UTF-16LE 是否安全?或者它是特定于 MSVC 编译器的,并且它可以是(比如)GCC 中的UTF-16BE @avo 它是特定于平台的,而不是特定于编译器的。 Windows 是一个小端平台。话虽这么说,但可以通过额外的工作将 UTF-16BE 字符串存储在 std::wstringstd::u16string 中。 @VTT ARM 有 big-endian 和 little-endian 模式,但是 AFAIK,实际上几乎每个人都在 little-endian 模式下使用它。【参考方案2】:

我想对@jamesdlin 的anwser 进行修改,尽管他的回答是正确的。

在 C++11 之前,有 charwchar_t,因此将 std::basic_string&lt;&gt; 专门化为 std::stringstd::wstring

但是,wchar_t 的位宽度是特定于平台的:在 Windows 上为 16 位,而在其他平台上为 32 位。

而随着C++11的出现,标准的addschar16_t来表示16位宽的字符;因此在 Windows 上,std::u16string 在大多数情况下恰好可以与 std::wstring 互换,因为它们都能够表示 16 位宽的字符。

wchar_t 类型是实现定义的宽字符类型。在 Microsoft 编译器,它表示一个 16 位宽的字符,用于 存储编码为 UTF-16LE 的 Unicode,本机字符类型 Windows 操作系统。

但最新的 MSDN 似乎为使用 std::wstring 的代码添加了一些 aside notes,但打算移植:

wchar_t 的大小是实现定义的。如果您的代码取决于 wchar_t 是一定的大小,检查你的平台的实现 (例如,使用 sizeof(wchar_t))。如果你需要一个字符串字符 类型的宽度保证在所有情况下都保持不变 平台,使用字符串、u16string 或 u32string。

至于 LE(little-endian),它应该是特定于架构的,IIRC。并且当今大多数架构都使用 LE。

【讨论】:

任何关心可移植性的人都应该避免使用 UTF-16。它具有 UTF-8 和 UTF-32 的所有缺点,但没有它们的优点。由于时机不对,Windows 被 UTF-16 卡住了;当 Microsoft 添加 Unicode 支持时,UTF-8 还不存在。 @jam:如果您的可移植代码处理 UTF-16 编码的文件,那么您当然不应该避免使用 UTF-16。使用 UTF-16 也有一些优点:它是一种适用于各种代码点(整个 BMP)的固定宽度编码,并且它可以为某些亚洲文字提供更紧凑的表示。此外,如果您与 Java 或 .NET 交互,UTF-16 也是一个可行的选择。这就是上述两者都用作其内部字符串表示的内容。在此处选择 UTF-16 会导致更少的转换。

以上是关于wchar_t 和 char16_t 在 Windows 上是一样的吗?的主要内容,如果未能解决你的问题,请参考以下文章

C++ 几种字符类型学习

c++0x中wchar_t的命运如何?

关于 char wchar_t TCHAR _T() ||| 宏 _T TEXT _TEXT L

iostreams - 将 `wchar_t` 或 `charXX_t` 值打印为字符

基本内置类型

如何定义宏以将连接的char字符串转换为C中的wchar_t字符串