本文为原创文章,转载请注明出处,或注明转载自“黄邦勇帅(原名:黄勇)
本文是对《C++语法详解》一书相关章节的增补,以增强读者对字符的理解,因为《C++语法详解》引用的标准过于老旧。
《C++语法详解》网盘地址:
https://pan.baidu.com/s/1dIxLMN5b91zpJN2sZv1MNg
本文摘自本人所作《Unicode编码和双向算法(bidi)详解》网盘地址
链接:https://pan.baidu.com/s/1LLKv22jQPmeba1XUCm0xoQ?pwd=a3x8
提取码:a3x8
有兴趣的读者可参阅本人所著《C++语法详解》一书,电子工业出版社出版,该书语法示例短小精悍,对查阅C++知识点相当方便,并对语法原理进行了透彻、深入详细的讲解,可确保读者彻底弄懂C++的原理,彻底解惑C++,使其知其然更知其所以然。此书是一本全面了解C++不可多得的案头必备图书。
由于本人能力有限,文中难免有错漏之处,望广大读者指出更正,不胜感激
注意:若对本文的专业术语不了解,请参阅本系列文章(一)和(二)
UTF-16是变长编码方式,每个字符编码为2或4字节。
代理可简单理解为代替,其基本思想就是使用两个基本平面中未定义(或未使用)的码点合起来代替一个增补平面的码点。
代理对是指基本平面中用来代替增补平面码点的两个码点,也就是说,代理对是一对(即,两个)码点值。
代理区
把高代理码点和低代理码点合起来组成“代理对”,使用代理对来代替增补平面的码点,代理对刚好可完全表示增补平面内的所有码点(原因见后文)。比如,增补平面的第一个码点0x10000的UTF-16编码是0xD800 DC00,同理,第二个码点0x10001的UTF-16编码是0xD800 DC01,其余以此类推。
根据UTF-16的编码规则可制出如表6所示的一个表格,然后通过查表的方式查找增补字符的编码,但这种方法非常麻烦,实际编码时并不使用。
①、将增补字符的码点值减去0x10000,得到一个20位长的二进制数
②、将得到的20位长二进制数拆分为高10位比特和低10位比特
③、20位长的高10位比特加上0xD800得到第一个代理码点,即高代理码点
④、20位长的低10位比特加上0xDC00得到第二个代理码点,即低代理码点
⑤、将得到的高代理码点和低代理码点组合成“代理对”,便得到了增补字符的UTF-16编码
⑥、示例:求增补平面码点值为U+10437的UTF-16编码
将0x10437减去0x10000,得到0x00437,二进制为0000 0000 0100 0011 0111
将高10位,即0000 0000 01加上0xD800(二进制为1101 1000 0000 0000),得到高代理码点为:0xD801(二进制为1101 1000 0000 0001)
将低10位,即00 0011 0111加上0xDC00(二进制为1101 1100 0000 0000),得到低代理码点为:0xDC37(二进制为1101 1100 0011 0111)
将高代理码点和低代理码点组合成代理对得到UTF-16编码为0xD801 DC37
①、原理
高代理码点的起始值0xD800(二进制为1101 1000 0000 0000)和低代理码点的起始值0xDC00(二进制为1101 1100 0000 0000),可发现,他们的前6位分别为110110和110111,而后10位都是0,总共有20位(220=1048576),刚好可表示增补平面中的所有码点(0x10000 ~ 0x10FFFF,共220=1048576个码点),若利用代理码点的这20位来表示增补码点,则高代理码点的范围为1101 1000 0000 0000(0xD800) ~ 1101 1011 1111 1111(0xDBFF),低代理码点的范围为1101 1100 0000 0000(0xDC00) ~ 1101 1111 1111 1111(0xDFFF),刚好在高代理码点和低代理码点的范围内。因此,可利用填补二进制位的方法来编码UTF-16
②、步骤1:
将高代理码点和低代理码点分别展开为如图4所示的形式,其中高代理单元的110110和低代理单元的110111是固定不变的数(定数),p和x是变数,去掉定数后组合起来就是pppp xxxx xxxx xxxx xxxx,共20位,刚好可表示全部增补码点,其中pppp表示16个增补平面的编码(24=16),紧接着的16个x表示某个增补平面内的码点。
③、步骤2、
将增补字符的码点值减去0x10000,得到一个20位长的二进制数
④、步骤3、
将得到的20位长二进制数依次填补步骤1中的变数便得到UTF-16的编码
⑤、示例:
求增补平面码点值为U+10437的UTF-16编码
UTF-16编码后的码元序列在映射为物理意义上的字节序列时,又分为UTF-16BE (大端序),UTF-16LE (小端序)两种情况,大端序和小端序又分为带有字节序标记(with BOM)和不带字节序标记(without BOM)两种情形。比如,“ABC”这三个字符的UTF-16编码(码元序列)为:00 41 00 42 00 43;其对应的各种字节序列如表7所示: