Unicode UTF-16编码如何使用代理代码点?

Unicode UTF-16编码如何使用代理代码点?,unicode,utf-16,Unicode,Utf 16,根据 D91 UTF-16编码格式:分配每个 范围为U+0000..U+D7FF和U+E000..U+FFFF的Unicode标量值 到具有与相同数值的单个无符号16位代码单元 Unicode标量值,指定每个Unicode标量值 范围为U+10000..U+10FFFF到代理项对 术语“标量值”指的是unicode代码点,即必须通过不同编码形式(UTF-16等)将抽象概念编码为特定字节序列的范围。因此,这一摘录要点似乎是考虑到并非所有的代码点都可以容纳在一个UTF-16代码单元(两个字节)中,有

根据

D91 UTF-16编码格式:分配每个 范围为U+0000..U+D7FF和U+E000..U+FFFF的Unicode标量值 到具有与相同数值的单个无符号16位代码单元 Unicode标量值,指定每个Unicode标量值 范围为U+10000..U+10FFFF到代理项对

术语“标量值”指的是unicode代码点,即必须通过不同编码形式(UTF-16等)将抽象概念编码为特定字节序列的范围。因此,这一摘录要点似乎是考虑到并非所有的代码点都可以容纳在一个UTF-16代码单元(两个字节)中,有些代码点应该编码到一对代码单元(4个字节)中(称为“代理对”)

然而,术语“标量值”的定义如下:

D76 Unicode标量值:除高代理外的任何Unicode代码点 和低代理代码点


等等。。。Unicode是否有代理代码点?当UTF-16可以使用4个字节来表示标量点时,原因是什么?有人能解释一下基本原理以及UTF-16如何使用此代码点吗?

是的,Unicode保留了代理代码点的范围:


Unicode保留这些范围,因为这些16位值在代理项对中使用,并且不能为它们分配其他符号。代理项对是两个16位值,它们对U+FFFF以上的代码点进行编码,这些代码点不适合于单个16位值。

仅为最终澄清起见

  • UTF-16使用16位(2字节)代码单元。这意味着这种编码格式将代码点(即抽象思想应该以某种方式在计算机内存中表示)编码为16位(因此据称解释器一次读取两个字节的数据)
  • UTF-16做得最好非常简单:U+000E编码点将编码为000E,U+000F编码为000F,依此类推
  • 问题是16位只能提供不足以容纳所有unicode代码点的范围(0000..FFFF仅允许65536个可能值)。对于超出此范围的代码点,我们可能会使用两个16位字(4字节)(实际上,我的误解是UTF-16为什么不这样做)。然而,这种方法导致无法解码某些值。例如,如果我们将U+10000代码点编码为0001 0000(十六进制表示法),那么解释器究竟应该如何解码这种表示:作为两个子量化代码点U+0001和U+0000,还是作为单个U+10000
  • Unicode规范倾向于更好的方式。如果需要对范围U+10000..U+10FFF(1 048 576个代码点)进行编码,那么我们应该将1 024+1 024=2 048的值与那些可以用16位编码的值分开(规范为其选择了D800..DFFF范围)。当interpeter在计算机内存中计算D800..DBFF(高代理区域)值时,它知道这不是隐含的“完全成熟”代码点(不是规范中的标量值),它应该再读取16位以从DC00..DFFF范围(低代理区域)中获取值最后得出U+10000..U+10FFF代码点中的哪一个是用这4个字节(用这个代理项对)编码的。注意,这样的方案可以对1024*1024=1048576个代码点进行编码(这与我们需要的数量非常相同)
  • 由于Unicode代码空间被定义为从0到10FFFF的整数范围,因此我们必须引入代理代码点(而不是代码单位)的概念——U+D800..U+DBFF范围(因为我们不能从Unicode代码空间中排除此范围)。鉴于为UTF-16中的代理代码单元指定了代理代码点(见C1,D74),这些代码点可以视为UTF-16遗迹