维基百科有详细文章:https://en.wikipedia.org/wiki/Unicode_in_Microsoft_Windows
我将首先解释 Windows 支持的三种类型的字符串文本编码:
- “ANSI” = 8 位编码 - C 中的
char。尽管名称为“ANSI”,但它不是 ASCII 不一定是任何特定的 ANSI 编码或 ASCII,但无论当前的语言环境/代码页是什么。
- "MBCS" = 多字节字符集编码 - C 中的
char(其中每个字节是 char。支持的代码页列表是有限的,关键是它不包括 UTF-8。请参阅此 QA:@987654322 @)。 MBCS 在现代 Windows 中已弃用,不应在新项目中使用。
- "Unicode" = UTF-16(或 NT3/NT4 中的 UCS-2)- C 中的
wchar_t,即 16 位。
- 在 UCS-2 下,只能使用由代码点
0x0000-0xFFFF 表示的字符。不能使用超出此范围的字符。
- 在 UTF-16(Windows 2000 及更高版本)中,
0xFFFF 之后的代码点由 2 个或更多 wchar_t 值(4 个或更多字节)表示,称为 surrogate-pairs,表示字符串的二进制长度(以字节为单位)不一定与字符串的元素长度(在size_t 中)成正比,也不一定与打印字符的数量成正比。
- 还要考虑诸如连字和变音符号之类的东西也会打破编程代码经常做出的字节/元素/打印字符计数等价假设。
- 作为示例,请考虑以下代码点字符串:
U+0061, U+0928, U+093F, U+4E9C, U+10083
- 在 UTF-16 Big-Endian 字节中,这是
00 61 09 28 09 3F 4E 9C D8 00 DC 83
- 12字节
- ...这是 6 个
wchar_t 元素
- ...但代表 5 个字符
- ...呈现为 4 个打印字符(由于第 2 和第 3 个字符之间的连字)。
Windows 3.x
Windows 3.x 实现了 16 位 Windows API,严格来说是 8 位。如果不运行 en-US 版本,它将使用当前的默认语言环境和代码页设置。它不支持宽字符,但大概支持某种 MBCS。
Windows 3.x 的“Win32 子集”(“Win32s”)附加组件在 Windows 3.x 中添加了一些 Win32 函数,包括 A 和 W 函数,但是 W 函数是存根的,并且调用时返回失败代码 - 与在 Windows 95 上的“完整”Win32 上看到的行为相同。
Windows 95、98、我:
在 Windows 9x(95、98、Me)上实现的 Win32 不支持 UTF-16,仅支持“ANSI”或“MBCS”字符串。
重要的一点是,与 Win32s 一样,"Wide-character" functions do exist on Windows 9x, but they are stubbed out and when called will return failure codes - 除了处理 UCS-2 字符串的a handful of Resource, Command-line and MessageBox-related functions(例如MessageBoxExW)。
支持非拉丁字符集需要弄乱代码页和神秘的“多字节”编码选项(请记住,不支持 UTF-8 - MultiByteToWideChar 和 WideCharToMultiByte 除外 - 可用于转换UTF-8 到 UTF-16 用于 Win32 API)。
2001 年,Microsoft 为 Windows 9x 发布了一个名为 Microsoft Layer for Unicode (MSLU) 的附加组件,它将 W 函数从失败存根更改为 thunking 代理,将字符串转换回 8 位格式和然后调用A 函数,因此显式使用W 函数的程序可以在Windows 9x 上运行。
Windows NT
Windows NT,从一开始就带有接受wchar_t 类型参数的W 函数的NT 3.1(没有3.0 版本)。字符串使用 UCS-2(NT3、NT4)或 UTF-16(NT5 及更高版本)编码。 Microsoft 产品和文档通常使用“Unicode”作为 UTF-16 或 UCS-2 的简写。 Win32 不支持 UTF-8(MultiByteToWideChar 和 WideCharToMultiByte 除外),因此模棱两可几乎无法通过。
Windows CE
Windows CE 1.0 从一开始就支持 UTF-16,认为它的支持级别相当于 Windows NT 家族的支持级别。我不知道 CE 何时或是否曾经支持 UCS-2 而不是 UTF-16,或者它是否从一开始就是 UTF-16。
简而言之:
OS ANSI | MBCS | UTF-16 ("Unicode")
-----------------------------------------------------------------------------
Windows 3.x (Stock) Yes | ? | No
Windows 3.x (Win32s) Yes | ? | Stubbed, always fails (a)
Windows 95, 98, ME Yes | Yes | Limited support (b) otherwise fails
Windows 95, 98, ME (MSLU) Yes | Yes | Yes, runtime thunked to ANSI (c)
Windows NT 3.x, NT 4.x Yes | Yes | As UCS-2 instead of UTF-16 (d)
Windows 2000 and later Yes | Yes | Yes
Windows CE 1.0 and later Yes | ? | Yes (e)
(a): https://msdn.microsoft.com/en-us/library/cc194796.aspx
(b):https://support.microsoft.com/en-us/kb/210341
(c):https://en.wikipedia.org/wiki/Microsoft_Layer_for_Unicode
(d):https://en.wikipedia.org/wiki/Unicode_in_Microsoft_Windows
(e):http://www.hpcfactor.com/support/windowsce/wce1.asp
结论:只需使用“Unicode”即可:即使您正在编写针对 Windows 9x 的软件,您也可以使用 Unicode 层并且它仍然可以运行(尽管类似Unicode 文件名和窗口标题可能很奇怪)。您的代码也可以移植到 Windows CE(我很惊讶地看到 Windows CE 从一开始就支持 UTF-16)。