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

问题描述 投票:0回答:2

根据Unicode规范

D91 UTF-16编码形式:分配每个的Unicode编码形式 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 utf-16
2个回答
2
投票

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

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


1
投票

只是为了最终澄清。

  • UTF-16 使用 16 位(2 字节)代码单元。这意味着这种编码格式通常将代码点(=抽象思想应该以某种方式在计算机内存中表示)编码为 16 位(因此解释器可能一次将数据读取为两个字节)。
  • UTF-16 的表现非常简单:
    U+000E
    代码点将被编码为
    0x000E
    U+000F
    0x000F
    ,依此类推。
  • 问题是 16 位只能提供不足以容纳所有 unicode 代码点的范围(
    0x0000
    -
    0xFFFF
    范围仅允许 65 536 个可能的值)。我们可能会使用两个 16 位字(4 个字节)来表示超出这些边界的代码点(实际上,我的误解是为什么 UTF-16 不这样做)。然而,这种方法会导致无法解码某些值。例如,如果我们将
    U+10000
    代码点编码为
    0x00010000
    ,解释器究竟应该如何解码这种表示:作为两个不同的连续代码点,
    U+0001
    U+0000
    ,或者作为单个代码点,
    U+10000
  • Unicode 规范决定了一种更好的方式。如果需要对
    U+10000
    -
    U+10FFFF
    范围(顺便说一下,有 1 048 576 个代码点)进行编码,那么我们应该首先从单字节范围中分离出 1 024 + 1 024 = 2 048 个值(出于这些目的,规范选择了
    0xD800
    -
    0xDFFF
    )。当解释器遇到
    0xD800
    -
    0xDBFF
    值时,它知道这里没有编码隐含的“成熟”代码点(根据规范,没有标量值),然后它应该读取另外 16 位获取
    0xDC00
    -
    0xDFFF
    范围内的值,并最终得出
    U+10000
    -
    U+10FFF
    代码点中的哪一个是用这 4 个字节编码的。请注意,此方案可以编码 1 024 * 1 024 = 1 048 576 个代码点(这正是我们需要的数量)。
  • Unicode 规范仅在其 Unicode 代码空间中包含此整数范围,这是从
    U+0000
    0x10FFFF
    的代码点空间。那么
    U+D800
    -
    U+DFFF
    子空间在其中被称为 High Surrogate Area
    U+DC00
    -
    U+DFFF
    Low Surrogate Area。由于这些代码points的值与UTF-16代码units的值相匹配(=代码点的具体表示),因此该包含可以被视为UTF-16遗迹:

高代理和低代理代码点指定用于 UTF-16 字符编码形式的代理代码单元。他们是 未分配给任何抽象字符。 [规格]

© www.soinside.com 2019 - 2024. All rights reserved.