解释

Surrogate Pairs 主要是针对增补字符,此时一个16位的编码(2个Byte的UTF-16)已经无法表示,所以就扩展成需要两个16位的编码单元。也就是说,在范围U+10000到U+10FFFF间的编码则​使用一对16位编码单元​表示,称作代理对(surrogate pair)。

在BMP内的字符,仍然按照​​UTF-16​​的编码规则,使用两个字符来表示。 (注:BMP内的字符编码,不包含从U+D800到U+DFFF的预留码位。这些预留码位就恰好用于扩展字符编码)

增补字符的编码值已经超过了BMP的编码范围,需要使用一对UTF-16字符来表示一个字符。把Unicode编码记作U。编码规则如下:


  • 如果U<0x10000,U的UTF-16编码就是U对应的16位无符号整数。
  • 如果U≥0x10000,

  • 先计算U’=U-0x10000,
  • 然后将U’写成二进制形式:yyyy yyyy yyxx xxxx xxxx,(注意这里共计20位)
  • U的UTF-16编码(二进制)就是:110110yyyyyyyyyy 110111xxxxxxxxxx。


这两个字符就称为surrogate pair(代理对)。第一个代理字符为16位编码,范围为U+D800到U+DBFF,第二个代理字符也是一个16位编码,范围为U+DC00 to U+DFFF。


Wikipedia Examples

在wikipedia上有一个计算的例子,原则上和上面是一样的,表述略有不同:

把 U+10437 (?) 转换成 UTF-16:


  • 0x10437- 0x100000 = 0x0437.
  • high surrogate: 0x0437右移10位 (相当于除以0x400,也相当于扩展成20位之后,取左边的高10位), 然后加上 0xD800,得到:0x0001 + 0xD800 = 0xD801.
  • low surrogate, 取低10位(相当于对0x400取余), 然后加上0xDC00, 得到:0x0037 + 0xDC00 = 0xDC37.

从 UTF-16 解码 U+10437 (?) :


  • 取high surrogate, 0xD801 - 0xD800(等价于:0xD801&0x3FF), 结果再乘以 0x400, 得到:(0xD801-0xD800)×0x400=0x0001×0x400=0x0400
  • 取low surrogate,0xDC37-0xDC00(等价于:0xDC37&0x3FF), 得到:(0xDC37-0xDC00) = 0x0037.
  • 把上述两个结果相加,0x0400+ 0x0037 =0x0437, 最后加上0x10000得到0x10437,这个就是最终的UTF-32 code point, 0x10437.

The following table summarizes this conversion, as well as others. The colors indicate how bits from the code point are distributed among the UTF-16 bytes. Additional bits added by the UTF-16 encoding process are shown in black.

Character

Binary code point

Binary UTF-16

UTF-16 hex

code units

UTF-16BE

hex bytes

UTF-16LE

hex bytes

​$​

​U+0024​

​0000 0000 0010 0100​

​0000 0000 0010 0100​

​0024​

​00 24​

​24 00​

​€​

​U+20AC​

​0010 0000 1010 1100​

​0010 0000 1010 1100​

​20AC​

​20 AC​

​AC 20​

​?​

​U+10437​

​0001 0000 0100 0011 0111​

​1101 1000 0000 0001 1101 1100 0011 0111​

​D801 DC37​

​D8 01 DC 37​

​01 D8 37 DC​

​?​

​U+24B62​

​0010 0100 1011 0110 0010​

​1101 1000 0101 0010 1101 1111 0110 0010​

​D852 DF62​

​D8 52 DF 62​

​52 D8 62 DF​


应用举例:

python的源码(UnicodeObject.h)中有这么几个定义,

1。用来判断是否有UTF-16代理surrogate,

#define Py_UNICODE_IS_SURROGATE(ch)     (0xD800 <= (ch) && (ch) <= 0xDFFF)

#define Py_UNICODE_IS_HIGH_SURROGATE(ch)     (0xD800 <= (ch) && (ch) <= 0xDBFF)

#define Py_UNICODE_IS_LOW_SURROGATE(ch)      (0xDC00 <= (ch) && (ch) <= 0xDFFF)

2。从UTF16解码的过程如下,

#define Py_UNICODE_JOIN_SURROGATES(high, low)  \

    (((((Py_UCS4)(high) & 0x03FF) << 10) |      \

      ((Py_UCS4)(low) & 0x03FF)) + 0x10000)

注:Py_UCS4定义:typedef uint32_t Py_UCS4;

3。取得high surrogate和low surrogate的宏代码如下

/* high surrogate = top 10 bits added to D800 */

#define Py_UNICODE_HIGH_SURROGATE(ch) (0xD800 - (0x10000 >> 10) + ((ch) >> 10))

/* low surrogate = bottom 10 bits added to DC00 */

#define Py_UNICODE_LOW_SURROGATE(ch) (0xDC00 + ((ch) & 0x3FF))


【1】 ​​https://en.wikipedia.org/wiki/UTF-16​