今天想通过 自己设计一个 Unicode 的 编码 来了解字符编码, 结果和真正的 UTF-8 对比, 发现有一些出入, 搜索不到相应的信息, 所以有了这个小小的疑问, 不知道 UTF-8 是一开始就设计成这样还是逐步演变成这样的?
utf-8 是字符集 unicode 的一种不定长的编码格式, 一个 code point 会用 1-4 个字节表示, 具体用多少字节取决于 codepoint 落在哪个区间.

它具体的编码规则是(来源):
以汉字严为例,演示如何实现 UTF-8 编码。 严的 Unicode 是 4E25 ( 100111000100101 ),根据上表,可以发现 4E25 处在第三行的范围内( 0000 0800 - 0000 FFFF ),因此严的 UTF-8 编码需要三个字节,即格式是 1110xxxx 10xxxxxx 10xxxxxx。然后,从严的最后一个二进制位开始,依次从后向前填入格式中的 x,多出的位补 0。这样就得到了,严的 UTF-8 编码是 11100100 10111000 10100101,转换成十六进制就是 E4B8A5。
但是为什么 UTF-8 不用完所有的有效 bit 呢?
- 拿上图的两个字节来说, 第一个字节有 5 个 x, 第二个字节 6 个 x, 11 bit 的有效位, 完全可以表示 2^11=2048 个码点, 但 UTF-8 只用来表示 [0x80, 0x7ff] 这个区间(一共 1920 个)的码点, 低位的 128 个值都被浪费了: 110 00000 10 000000 ~ 110 00001 10 111111 这些值都空着.
- 再看三个字节: 一共 16 bit 的有效载荷, 可以表示 2^16 = 65536 个码点, 但 UTF-8 也只用了其中的 63488 个, 低位的 2048 个值空着.
UTF-8 是为了省空间而设计的, 是要把这些有效位塞满的吧? 两个字节就把所有的值用上:
- 最小值 110 00000 10 000000 有效 bit 的值是 0, 加上 0x80 的偏移量, 用来表示 0x80 这个码点
- 最大值 110 11111 10 111111 有效 bit 的值是 0x7FF, 加上 0x80 的偏移量, 可以用来表示 0x87f 这个码点
- 表示的范围是 [0x80, 0x87f].
- 四个字节的同理, 用满所有的有效 bit, 可以多表示 2048 个码点.
难道 UTF-8 让这些位置空着, 就为了不用做额外的加减偏移量的操作? 有了解的老哥来解惑一下么? 有来源就最好了