语言在底层如何表示 UTF-8?

Nic*_*ick -1 c++ utf-8 character-encoding

我最近看了Computerphile 的 Tom Scott 谈论 UTF-8,之后进行了一些研究,了解到 UTF-8 可用于对最多 6 个字节的字符进行编码,每个字节使用以下标头:

0xxx xxxx    # 1 Byte character
110x xxxx    # 2 Byte character
1110 xxxx    # 3 Byte character
1111 0xxx    # 4 Byte character
1111 10xx    # 5 Byte character
1111 110x    # 6 Byte character
Run Code Online (Sandbox Code Playgroud)

然后用它10xx xxxx来表示额外的字节(我知道RFC3629将其限制为最多 4 个字节)。

我的理解是否正确,这允许对 2,164,286 个不同的字符进行编码(忽略任何保留字符)?

0xxx xxxx    # 7 bits                      =>       128
110x xxxx    # 5 bits + 6 bits   = 11 bits =>     2,048
1110 xxxx    # 4 bits + 6*2 bits = 16 bits =>    65,536
1111 0xxx    # 3 bits + 6*3 bits = 21 bits => 2,097,152
             #                             == 2,164,864
Run Code Online (Sandbox Code Playgroud)

理论上,我可以使用char数组来存储 UTF-8 编码的字符串,或者我可以使用固定长度编码(如 UTF-32)并使用任何 4 字节类型(例如对unsigned long每个 UTF-8 编码字符进行编码),但这会增加对于仅使用 1 或 2 个字节编码的 UTF-8 字符的文本,内存会显着增加。

我相信std::string允许存储UTF-8,这将导致sizelength返回字节长度,但是如果UTF-8可以表示不同长度的字符,那么语言(我们将采用C++来限制这个问题的范围)如何编码这些字符内部(例如在std::string)?

Bas*_*tch 5

UTF-8 字符串是遵循一些限制的字节序列(即 -scharuint8_tC++ 中的字节序列)(因此并非每个字节序列都是有效的 UTF-8 字符串;如果您从外部获取某个字符串,该字符串声称它是是 UTF-8,您应该验证它)。

因此,您可以使用std::string-s 来表示 UTF-8 字符串(前提是您确定它们是有效的 UTF-8)。

您可以在它们之上使用一些 UTF-8 库(例如libunistringGlib Unicode Manipulation)。

换句话说,UTF-8 可以看作是关于如何使用字符串(of -s)的约定char

当然,请注意字节数(例如size() a std::string)不是UTF -8 字符数。并且您不能使用普通迭代器来迭代 UTF-8 字符(或其等效的 Unicode)。

您可能会发现更多支持 UTF-8 的 C++ 库(例如Gtkmm 中的Glibmm ustring -s)或其他表示 Unicode 字符串的库(例如Qt 中的QString -s)。

顺便说一句,UTF-8(和 Unicode)在屏幕或纸张上正确渲染非常复杂(因此您需要一些库来实现)。您可能在同一个字符串中混合了多种语言(英语、俄语、阿拉伯语、中文),其中一些语言正在改变方向。您可能有组合字符(重音等)。Unicode 相当复杂(我不知道其中大部分,因为我不知道大多数人类语言;我只能说和读英语、法语、俄语。我可以破译一些希腊字母。我只知道很少的希伯来语字母。而中文对我来说完全是陌生的)。

另请参阅http://utf8everywhere.org/和有关UTF-8Unicode的维基页面。

  • 当然。您可以决定使用 Unicode 字符的字符串(例如“uint32_t”)。您可能不想这样做。 (4认同)