gpt4 book ai didi

c++ - 16 位 wchar_t 是否正式代表完整的 Unicode?

转载 作者:可可西里 更新时间:2023-11-01 18:38:20 24 4
gpt4 key购买 nike

在 ¹comp.lang.c++ Usenet 组中,我最近断言,基于我所知道的,Windows 的 16 位 wchar_t,使用 UTF-16 编码,其中有时有两个这样的值(称为“代理对”)对于单个 Unicode 代码点是必需的,对于表示 Unicode 是无效的。

虽然 Unicode 联盟 2004 年的技术说明 12 为使用用于内部处理的 UTF-16,以及一系列令人印象深刻的软件。

显然,最初的意图似乎是每个代码点有一个wchar_t 值,这与C 和C++ 标准库的假设一致。例如。在 ³unix.org 的网页“ISO C 修正案 1 (MSE)”中,关于在 1995 年将 wchar_t 纳入 C 标准的修正案,作者认为

The primary advantage to the one byte/one character model is that it is very easy to process data in fixed-width chunks. For this reason, the concept of the wide character was invented. A wide character is an abstract data type large enough to contain the largest character that is supported on a particular platform.

但事实证明,C 和 C++ 标准似乎并没有讨论支持的最大字符,而只讨论了支持的语言环境中最大的扩展字符集 : wchar_t 必须足够大以表示最大的此类扩展字符集中的每个代码点——但不是 Unicode,当没有 Unicode 语言环境时。

C99 §7.17/2(来自 N869 草案):

[the wchar_t type] is an integer type whose range of values can represent distinct codes for all members of the largest extended character set specified among the supported locales.

这几乎与 C++ 标准中的措辞相同。这似乎意味着,在受支持的区域设置受限的情况下,wchar_t 确实可以很小,使用 UTF-8 编码可以降低到单个字节(这是一种噩梦,例如没有标准库字符分类函数会在 ASCII 的 A 到 Z 之外工作,但是嘿)。可能以下是比这更宽的要求:

C99 §7.1.1/4:

A wide character is a code value (a binary encoded integer) of an object of type wchar_t that corresponds to a member of the extended character set.

... 因为它指的是 扩展字符集,但该术语似乎没有在任何地方进一步定义。

至少对于 Microsoft 的 C 和 C++ 运行时,没有 Unicode 语言环境:使用该实现 setlocale 仅限于每个字符最多 2 个字节的字符编码:

MSDN ⁴setlocale 的文档:

The set of available locale names, languages, country/region codes, and code pages includes all those supported by the Windows NLS API except code pages that require more than two bytes per character, such as UTF-7 and UTF-8. If you provide a code page value of UTF-7 or UTF-8, setlocale will fail, returning NULL.

所以看来,与我所知道的相反,也与我的断言相反,Windows 的 16 位 wchar_t 在形式上是可以的。主要是由于 Microsoft 巧妙地缺乏对 UTF-8 语言环境或每个字符超过 2 个字节的任何语言环境的支持。但是真的是这样吗,16位的wchar_t可以吗?


<支持>链接:
¹ 新闻:comp.lang.c++
² http://unicode.org/notes/tn12/#Software_16
³ http://www.unix.org/version2/whatsnew/login_mse.html
https://msdn.microsoft.com/en-us/library/x99tb11d.aspx

最佳答案

wchar_t 现在不是,也从来不是 Unicode 字符/代码点。 C++ 标准并未声明宽字符串文字将包含 Unicode 字符。 C++ 标准并未声明宽字 rune 字将包含 Unicode 字符。事实上,该标准没有说明 任何 wchar_t 将包含的内容。

wchar_t 可以与可识别区域设置的 API 一起使用,但它们仅与实现定义的编码相关,而不是任何特定的 Unicode 编码。采用这些的标准库函数使用它们对实现编码的了解来完成它们的工作。

那么,16 位的wchar_t 合法吗?是的;该标准不要求 wchar_t 足够大以容纳 Unicode 代码点。

wchar_t 的字符串是否允许保存 UTF-16 值(或一般的可变宽度)?好吧,您可以制作 wchar_t 字符串来存储您想要的任何内容(只要它适合)。因此,就标准而言,问题是是否允许标准提供的用于生成 wchar_t 字符和字符串的方法使用 UTF-16。

好吧,标准库可以为所欲为;该标准不保证从任何特定字符编码到 wchar_t 的转换将是 1:1 映射。即使是通过 wstring_convert 进行的 char->wchar_t 转换也不需要标准中的任何地方来生成 1:1 字符映射。

如果编译器希望声明宽字符集由 Unicode 的基本多语言平面组成,那么像这样的声明 L'\U0001F000' 将生成单个 wchar_t。但是这个值是实现定义的,根据 [lex.ccon]/2:

The value of a wide-character literal containing a single c-char has value equal to the numerical value of the encoding of the c-char in the execution wide-character set, unless the c-char has no representation in the execution wide-character set, in which case the value is implementation-defined.

当然,C++ 不允许将代理项对用作c-char\uD800 是一个编译错误。

标准中变得模糊的地方是如何处理包含字符集之外的字符的字符串。上面的文字表明实现可以做他们想做的事。然而,[lex.string]\16 是这样说的:

The size of a char32_t or wide string literal is the total number of escape sequences, universal-character-names, and other characters, plus one for the terminating U’\0’ or L’\0’.

我说这很模糊,因为没有说明如果字符串文字中的 c-char 超出目标字符集的范围时应该采取什么行为。

Windows 编译器(VS 和 GCC-on-Windows)确实会导致 L"\U0001F000" 的数组大小为 3(两个代理项对和一个 NUL 终止符)。这是合法的 C++ 标准行为吗?为超出字符集有效范围的字符串文字提供 c-char 是什么意思?

我会说这是标准中的漏洞,而不是那些编译器中的缺陷。它应该更清楚这种情况下的转换行为应该是什么。


无论如何,wchar_t 都不是处理 Unicode 编码文本的合适工具。它对于表示 任何形式 的 Unicode 不是“正式有效的”。是的,许多编译器将宽字符串文字实现为 Unicode 编码。但由于标准不要求这样做,您不能依赖它。

很明显,您可以将任何适合 wchar_t 的内容粘贴进去。因此,即使在 wchar_t 为 32 位的平台上,您也可以将 UTF-16 数据推送到其中,每个 16 位字占用 32 位。但是您不能将此类文本传递给任何需要宽字符编码的 API 函数,除非您知道这是该平台的预期编码。

如果您想使用 Unicode 编码,基本上不要使用 wchar_t

关于c++ - 16 位 wchar_t 是否正式代表完整的 Unicode?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39548465/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com