UTF-8将码点的重要位存储在码元低位中。
那需要解码器检查过长的序列(例如
U+0000-U+007F 0xxxxxxx
U+0080-U+07FF 110xxxxx 10xxxxxx
U+0800-U+FFFF 1110xxxx 10xxxxxx 10xxxxxx
U+10000-U+10FFFF 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx
那需要解码器检查过长的序列(例如
C0 80
而不是00
),并且还会减少可编码到固定字节数的代码点数量。如果它使用相同的编码,但将代码点映射如下:
- 前128个代码点(U+0000—U+007F):1个字节
- 接下来的2048个代码点(U+0080—U+087F):2个字节。例如
C0 81
:U+0081 - 接下来的65536个代码点(U+0880—U+1087F):3个字节。例如
E0 B0 B1
:U+0881 - 接下来的131072个代码点(U+10880—U+10FFFF,最高到U+20880):4个字节。例如
F0 B0 B0 B1
:U+10881
(即该值编码为范围开始处的偏移量)
如果使用较短的序列,就可以编码更多字符。解码也可能更快,因为它只需要与常量相加,这通常比检查过长的代码点的分支成本低。实际上,如果我们从映射中删除代理对范围,就可以将2048个字符压缩到3个字节中。
那么为什么UTF-8要以这种方式存储代码点呢?