88

在一个相关问题之后,我想问一下 C++11 中新的字符和字符串文字类型。看起来我们现在有四种字符和五种字符串文字。字符类型:

char     a =  '\x30';         // character, no semantics
wchar_t  b = L'\xFFEF';       // wide character, no semantics
char16_t c = u'\u00F6';       // 16-bit, assumed UTF16?
char32_t d = U'\U0010FFFF';   // 32-bit, assumed UCS-4

和字符串文字:

char     A[] =  "Hello\x0A";         // byte string, "narrow encoding"
wchar_t  B[] = L"Hell\xF6\x0A";      // wide string, impl-def'd encoding
char16_t C[] = u"Hell\u00F6";        // (1)
char32_t D[] = U"Hell\U000000F6\U0010FFFF"; // (2)
auto     E[] = u8"\u00F6\U0010FFFF"; // (3)

问题是://\x字符引用是否可以与所有字符串类型自由组合?是否所有的字符串类型都是固定宽度的,即数组包含的元素与文字中出现的元素数量一样多,或者/ /引用被扩展为可变数量的字节?和字符串是否具有编码语义,例如,我可以说非 BMP 代码点被编码为两个单元的 UTF16 序列吗?同样对于? 在(1)中,我可以用 写单独的代理吗?最后,是否有任何字符串函数编码感知(即它们是字符感知并且可以检测无效字节序列)?\u\U\x\u\Uu""u8""char16_t x[] = u"\U0010FFFF"u8\u

这是一个开放式问题,但我想尽可能完整地了解新 C++11 的新 UTF 编码和类型工具。

4

1 回答 1

59

\x/\u/\U 字符引用是否可以与所有字符串类型自由组合?

No.\x可以用于任何内容,但\u只能\U用于专门 UTF 编码的字符串。但是,对于任何 UTF 编码的字符串,\u\U可以根据需要使用。

所有的字符串类型都是固定宽度的,即数组包含的元素与文字中出现的元素数量一样多,或者对 \x/\u/\U 的引用被扩展为可变数量的字节?

不是你说的那样。\x, \u, 和\U基于字符串编码进行转换。这些“代码单元”(使用 Unicode 术语。Achar16_t是 UTF-16 代码单元)值的数量取决于包含字符串的编码。该文字u8"\u1024"将创建一个包含 2 chars 和一个空终止符的字符串。该文字u"\u1024"将创建一个包含 1char16_t加上一个空终止符的字符串。

使用的代码单元数基于 Unicode 编码。

u"" 和 u8"" 字符串是否具有编码语义,例如我可以说 char16_t x[] = u"\U0010FFFF",并且非 BMP 代码点被编码为两个单元的 UTF16 序列吗?

u""创建一个 UTF-16 编码的字符串。u8""创建一个 UTF-8 编码的字符串。它们将按照 Unicode 规范进行编码。

在 (1) 中,我可以用 \u 写单独的代理吗?

绝对不。该规范明确禁止使用 UTF-16 代理对 (0xD800-0xDFFF) 作为\uor的代码点\U

最后,是否有任何字符串函数编码感知(即它们是字符感知并且可以检测无效字节序列)?

绝对不。好吧,请允许我改述一下。

std::basic_string不处理 Unicode 编码。他们当然可以存储UTF 编码的字符串。但他们只能将它们视为charchar16_tchar32_t;的序列。他们不能将它们视为使用特定机制编码的 Unicode 代码点序列。basic_string::length()将返回代码单元的数量,而不是代码点。显然,C 标准库的字符串函数完全没用

但是应该注意的是,Unicode 字符串的“长度”并不意味着代码点的数量。一些代码点正在组合“字符”(一个不幸的名称),它与前一个代码点组合。因此,多个代码点可以映射到单个视觉字符。

Iostreams 实际上可以读/写 Unicode 编码的值。为此,您必须使用语言环境来指定编码并将其正确地融入到各个地方。这说起来容易做起来难,我没有任何代码可以告诉你如何做。

于 2011-07-23T00:34:07.670 回答