语言如何代表引擎盖下的UTF-8

How do languages represent UTF-8 under the hood?

本文关键字:UTF-8 引擎 何代表 语言      更新时间:2023-10-16

我最近看过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

然后使用 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

从理论上讲,我可以使用char数组来存储一个UTF-8编码的字符串,或者我可以使用诸如UTF-32之类的固定长度编码,并使用任何4个字节类型(例如unsigned long)来编码每个UTF-8编码的字符,但这将大大增加内存的文本,该文本仅使用用1或2个字节编码的UTF-8字符。

我相信std::string允许储存UTF-8,这将导致sizelength返回字节长度,但是如果UTF-8可以代表不同的字符长度,则如何使用语言(我们将带C 限制范围这个问题)内部对这些字符进行编码(例如std::string中)?

utf -8字符串是一个字节序列(即char-的序列)在某些限制之后,c 中的s或 uint8_t(因此,不是每个字节的每个序列都是有效的UTF-8字符串;如果从外部获得一些字符串,该字符串声称它是UTF-8,则应该验证它)。

>

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

您可以在上面使用一些UTF-8库(例如libunistring或libunistring或glib Unicode操纵)。

换句话说,UTF -8可以看作是A justruction 如何使用字符串(char -S的字符串)。

当然,请注意,字节数(例如std::stringsize())是不是 UTF-8字符的数量。而且您不能使用普通的迭代器对UTF-8字符(或它们的Unicode等效)进行迭代。

您可能会找到更多的UTF-8 Aware C 库(例如GTKMM中的GliBMM USTRING-S)或代表Unicode字符串的库(例如QT中的QString-S)。

btw,UTF-8(和Unicode)非常复杂,可以在屏幕或纸上正确渲染(因此您需要一些库)。您可能会在同一字符串中使用各种语言(英语,俄语,阿拉伯语,中文)的混合,其中一些正在改变方向。您可能具有组合字符(口音等)。Unicode非常复杂(而且我不知道其中的大多数人,因为我不知道大多数人类语言;我只能说和读英语,法语,俄语。我可以解读一些希腊语字母。我只知道很少的Hebraic信件。中文对我来说是完全陌生的)。

另请参见http://utf8everywhere.org/和utf-8和unicode上的wikipages。

c 标准无法地解决正确的UTF8处理,但是有些库可以通过编码点(实际字符,而不是字节)对字符串进行迭代。

通常将文本存储为一个字节的数组(一些奇怪的优化,例如标记的指针字符串),并且通常在其顶部添加了正确处理CODEPOINTS的轻质string views。例如,Swift编程语言采用此技术。

至于

,或者我可以使用固定的长度编码,例如UTF-32并使用任何 4个字节类型,例如未签名的长期来编码每个UTF-8编码 角色

C 11现在提供std::u8stringstd::u16stringstd::u32string,以方便起见。还有std::wstring通常应在便携式代码中避免使用,因为wchar_t的大小是编译器定义的,而不是标准定义的。

您直接到达正确点。据我所知,C 并不代表UTF-8。因此,它只是一种约定,实际上代表它的是生产和消费UTF-8的惯例。

现在,正如您所说的,UTF-8是围绕字节定向的,它允许您使用C 中的工具,例如STD :: String,它只是字节数组。虽然您只想将字符串发送到不知道标准的随机库,但许多事情可能会出错。在这里其他答案中提到的字符串大小,但更糟糕的是,非ASCII角色很可能会导致怪异的行为,因为这些角色中有一个以上的字节。

现在,关于UTF-8的好处是所有字符具有相同的代表,直至值128(其中包括所有英语字符)。因此,如果字符串的生产商尚不知道UTF-8,但消费者确实会起作用。

已经有许多库已经完成了这项工作,它们为UTF-8字符串提供了特殊类型,或者将std :: String读为UTF-8字符串。标准本身为您提供的字符串是每个字符都可以是一个以上的字节,例如std::u8stringstd::u16stringstd::u32string,在UTF-8的情况下,由于字符的大小在此标准中有所不同。

最后,一篇关于此主题的非常好的文章,该文章还涵盖了您在网上传递字符串时应该做什么:每个开发人员都必须了解Unicode

的最低限度