FreedomLy's blog.

UTF-8 码点

字数统计: 376阅读时长: 2 min
2017/10/09 Share

UTF-8的编码单元是8位字节,每个码点编成1至4个字节。它的编码方式很简单,按照码点的范围,把码点的二进制位拆分成1至最多4个字节:

码点范围 码点位数 字节1 字节2 字节3 字节4
U+0000~U+007F 7 0xxxxxxx
U+0080~U+07FF 11 110xxxxx 10xxxxxx
U+0800~U+FFFF 16 1110xxxx 10xxxxxx 10xxxxxx
U+10000~U+10FFFF 21 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx

1000 0000 -> 80
1100 0000 -> C0
1110 0000 -> E0
1111 0000 -> F0

1111 1111 -> FF
0011 1111 -> 3F

e.g. U+20AC 0x0800 < 0x20AC < 0xFFFF
所以0x20AC有16位码点,编成三字节
0x20AC的二进制为 10 0000 1010 1100 需要16位,所以在前面补0,即
0010 0000 1010 1100
将其分成三组:
0010, 000010, 101100
加上前缀:
1110 0010, 1000 0010, 1010 1100
则得到 0xE2, 0x82, 0xAC

10 0000 1010 1100 >> 12 -> 10 -> 0000 0010
0000 0010 & 1111 1111 -> 0000 0010
1110 0000 | 0000 0010 -> 1110 0010 -> 0xE2

10 0000 1010 1100 >> 6 -> 1000 0010
1000 0010 & 0011 1111 -> 0000 0010
1000 0000 | 0000 0010 -> 1000 0010 -> 0x82

10 0000 1010 1100 & 00 0000 1111 1111 -> 00 0000 1010 1100
00 0000 1000 0000 | 00 0000 1010 1100 -> 1010 1100 -> 0xAC

代码表示(C):

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
// u <= 0x007F
PUTC(c, u & 0xFF);

// u <= 0x07FF
PUTC(c, 0xC0 | ((u >> 6) & 0xFF));
PUTC(c, 0x80 | (u & 0x3F);

// u <= 0xFFFF
PUTC(c, 0xE0 | ((u >> 12) & 0xFF));
PUTC(c, 0x80 | ((u >> 6) & 0x3F));
PUTC(c, 0x80 | (u & 0x3F));

// u <= 0x10FFFF
PUTC(c, 0xF0 | ((u >> 18) & 0xFF));
PUTC(c, 0x80 | ((u >> 12) & 0x3F));
PUTC(c, 0x80 | ((u >> 6) & 0x3F));
PUTC(c, 0x80 | (u & 0x3F));

CATALOG