跳到主要内容
🚨 重要提示

本项目目前仍处于早期开发阶段,核心功能尚未完全实现,语法规范和工具链仍在持续完善中。

Unicode 编码标准介绍

UTF-8、UTF-16 和 UTF-32 都是 Unicode 编码 的不同实现方式,它们各自有不同的设计思想,适用于不同的存储和传输场景。我们可以从比特(bit)层面仔细看一下它们的编码设计。

1. UTF-8 编码

UTF-8 是一种变长编码方式,支持的字符范围从 U+0000U+10FFFF。它根据字符的 Unicode 码点(即字符的编号)使用 1 至 4 个字节来编码一个字符。UTF-8 的设计思想是通过 字节的高位 来标识当前字符需要多少个字节来表示。

设计规则

  • UTF-8 使用 1 到 4 个字节,并且每个字节的高位被用作标记当前字符是否需要后续字节。
  • 对于每个字节,前几个比特用于表示字符的信息,剩余比特用于续字节标记。

具体的编码规则如下:

  • 1 字节(7 位字符)

    • 对于 U+0000 到 U+007F 范围内的字符(即基本的 ASCII 字符),UTF-8 使用 1 个字节
    • 结构:0xxxxxxx(7 个有效位)
    • 例如:字符 A(U+0041)在 UTF-8 中编码为 0x41(即 01000001
  • 2 字节(11 位字符)

    • 对于 U+0080 到 U+07FF 范围内的字符,使用 2 个字节
    • 结构:110xxxxx 10xxxxxx(前导字节标志为 110,续字节标志为 10
    • 例如:字符 é(U+00E9)在 UTF-8 中编码为 0xC3 0xA9(即 11000011 10101001
  • 3 字节(16 位字符)

    • 对于 U+0800 到 U+FFFF 范围内的字符,使用 3 个字节
    • 结构:1110xxxx 10xxxxxx 10xxxxxx(前导字节标志为 1110,续字节标志为 10
    • 例如:字符 (U+4E2D)在 UTF-8 中编码为 0xE4 0xB8 0xAD(即 11100100 10111000 10101101
  • 4 字节(21 位字符)

    • 对于 U+10000 到 U+10FFFF 范围内的字符,使用 4 个字节
    • 结构:11110xxx 10xxxxxx 10xxxxxx 10xxxxxx(前导字节标志为 11110,续字节标志为 10
    • 例如:字符 𐍈(U+10348)在 UTF-8 中编码为 0xF0 0x90 0x8D 0x88(即 11110000 10010000 10001101 10001000

总结

  • UTF-8 使用 1 到 4 字节 来编码字符,每个字节的高位用于标识是否是续字节。
  • 字节结构:
    • 1 字节:0xxxxxxx
    • 2 字节:110xxxxx 10xxxxxx
    • 3 字节:1110xxxx 10xxxxxx 10xxxxxx
    • 4 字节:11110xxx 10xxxxxx 10xxxxxx 10xxxxxx

2. UTF-16 编码

UTF-16 是一种变长编码方式,使用 2 或 4 个字节 来表示字符。UTF-16 使用 16 位 来表示字符,支持的字符范围从 U+0000U+10FFFF。对于超出 BMP(基本多文种平面,U+0000 到 U+FFFF)的字符,UTF-16 使用 代理对(surrogate pairs) 机制来表示。

设计规则

  • U+0000 到 U+FFFF:使用 1 个 16 位单元(2 字节)

    • 结构:00000000 00000000(16 位)
    • 例如:字符 A(U+0041)在 UTF-16 中编码为 0x0041(即 00000000 01000001
  • U+10000 到 U+10FFFF:这些字符超出了 16 位,需要使用 2 个 16 位单元(4 字节),即 代理对(surrogate pairs)

    • 代理对的计算方式:
      • 首先从字符的码点中减去 0x10000(得到 20 位数)。
      • 然后将其分成两个部分:
        • 高位(高代理项):0xD800 | (high 10 bits)
        • 低位(低代理项):0xDC00 | (low 10 bits)
    • 例如:字符 𐍈(U+10348):
      • 减去 0x10000U+10348 - 0x10000 = 0x0348(20 位)
      • 高位:0xD800 | (0x0348 >> 10) = 0xD800 | 0x0003 = 0xD803
      • 低位:0xDC00 | (0x0348 & 0x3FF) = 0xDC00 | 0x348 = 0xDC48
      • UTF-16 编码为 0xD803 0xDC48(即 11010111 10000011 11011100 01001000

总结

  • UTF-16 使用 2 字节 表示字符(BMP 字符),并使用 代理对(两个 16 位单元,共 4 字节)表示超出 BMP 的字符。
  • 字符范围:
    • 1 单元(2 字节):00000000 00000000
    • 2 单元(4 字节,代理对):110110xxxx xxxx 110111xxxx xxxx

3. UTF-32 编码

UTF-32 是一种固定长度的编码方式,使用 4 个字节(即 32 位)来表示字符。它可以直接表示所有的 Unicode 字符,不需要变长或代理对。

设计规则

  • U+0000 到 U+10FFFF:每个字符都用 4 字节 表示。
    • 结构:00000000 00000000 00000000 xxxxxxxx(32 位)
    • 例如:字符 A(U+0041)在 UTF-32 中编码为 0x00000041(即 00000000 00000000 00000000 01000001
    • 例如:字符 (U+4E2D)在 UTF-32 中编码为 0x00004E2D(即 00000000 00000000 01001110 00101101

总结

  • UTF-32 使用 4 字节(32 位)来表示每个字符。
  • 字符范围:00000000 00000000 00000000 xxxxxxxx(32 位)

小结

  1. UTF-8:根据字符的 Unicode 码点使用 1 到 4 个字节编码,字节的高位用于标识是否为续字节。
  2. UTF-16:使用 2 字节表示基本字符,对于超出 BMP 的字符,使用 4 字节(代理对)表示。
  3. UTF-32:每个字符都使用 4 字节表示,不需要变长或代理对。

每种编码方式都有其应用场景:UTF-8 通常用于存储和传输数据,UTF-16 常用于程序内部处理(如 Java 和 Windows),UTF-32 则在需要直接支持所有字符的情况下使用,但会浪费内存。