我读到 C# 将 unicode 字符存储在char(又名System.Char)变量中,这些变量的长度固定为 16 位。然而,16 位不足以存储所有 Unicode 字符!在这种情况下,C# 的变量如何char支持 Unicode?
简而言之:代理人
这是一个很好的问题。Unicode比大多数人想象的要复杂,因为它引入了多个新概念(字符集、代码点、编码、代码单元),但我会尽力给出一个几乎完整的答案。
介绍:
Unicode 是一种字符集。字符集只是字符和代码点对的列表。代码点只是一个用于识别配对字符的数字。UTF-8、UTF-16 和 UTF-32 都是编码。编码定义如何以二进制形式(作为代码单元)表示数字(代码点)。代码单元可以由一个或多个字节组成。(实际上原始的 ASCII 代码单元甚至只有 7 位长,但那是另一个故事了)
请记住:字符集由代码点组成,编码由代码单元组成。
C#char类型表示 UTF-16 字符(代码单元)。UTF-16 是Unicode 字符集的可变长度/多字节编码。含义字符可以用1个或2个16位代码单元来表示。超过 16 位的 Unicode 代码点由两个等于 4 个字节的UTF-16 代码单元表示。
现在回答你的问题:如何?
Unicode 的最初想法是1 character = 1 code point。但原始编码 UCS-2(现已过时)使用两个字节(16 位),只能编码 65,536 个代码点。不久之后,这对于不断增长的 Unicode 字符集来说还不够。哦,真的,他们到底怎么想的?两个字节显然是不够的。为了解决这个问题,Unicode 必须放弃最初的想法并引入代理。
因此UTF-16诞生了,它是一种实现代理的可变长度/多字节(16位代码单元)编码。该代理项是特殊的 16 位代码单元,等于 Unicode 中定义的代码点,但明确不是字符。在解析文本时查找代理项意味着,您还必须读取接下来的 16 位并将这两个 16 位单元(代理项和后续代码单元)解释为一个组合的 32 位 Unicode 代码点。
UTF-32是固定的四字节编码,它足够大以避免空间问题,并且可以将 1 个字符映射到 1 个代码点,但 UTF-32 还必须处理代理项,因为 UTF 编码基于 Unicode 标准,并且代理项是 Unicode 字符集定义的一部分。
UTF-8也是一种可变长度/多字节编码,但采用了另一种有趣的编码技术。简而言之:代码单元中前导零的数量定义了最多四个后续字节的数量,这些字节必须组合成一个 Unicode 代码点。
| 归档时间: |
|
| 查看次数: |
1374 次 |
| 最近记录: |