Skip to content

Instantly share code, notes, and snippets.

@FrankHB
Created August 23, 2013 12:53
Show Gist options
  • Star 3 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save FrankHB/6319030 to your computer and use it in GitHub Desktop.
Save FrankHB/6319030 to your computer and use it in GitHub Desktop.
Outline for introducing character and text encoding.
1.多语言字符集和编码相关的参考规范之中最重要的有两个,一个是ISO/IEC 10646,一个是 Unicode 。
前者是专家委员会起草的国际标准。(前身还有两个不同的草案,因为中国大陆等方面的反对而否决。)
后者是行业协会组织的规范。ISO/IEC 10646正式版采用Unicode方案,之后的版本也和 Unicode 有基本的对应关系(虽然不一一对应),对普通应用来说基本可以作为同一个方案。
2.Unicode 定义了通用字符集(Universal Character Set, UCS) ,其中以代码点(code point) 作为逻辑上区分字符的单位。
由于历史原因,各种同源字符可能有不同的代码点,这方面汉字( CJKV unified ideographs ,中日韩越统一表意文字)问题尤其突出(相关工作称为Han Unification)。代码点可以由 U+X 的方式表示,X是16进制的自然数。
3.现行 UCS 代码点范围 U+0~U+10FFFF ,划分为 17 个平面,编号 0~16 ,每个平面有 65536 个代码点。
其中最常用的代码点子集是 0 号平面(代码点 U+0~U+FFFF ):基本多文种平面(basic mutilingual plane, BMP) ,之后是第一辅助平面:多文种补充平面(supplementary multilingual plane, SMP) 和第二辅助平面:表意文字补充平面(supplementary ideographic plane, SIP) 。第三至十三辅助平面尚未使用。第十四辅助平面称为特别用途补充平面(supplementary special-purpose plane, SSP) ,其中是控制字符。剩下的两个平面是私人使用区(private use area) 。
一个平面内的代码点可以被两个八元组(octet) 表示,也就是 16 位二进制整数。一般 C/C++ 实现使用的一个字节正好有 8 位,但不总是保证。
4.以 UCS 为基础可以表示文本编码。
早期使用 UCS 限定于现在的一个平面内,可以用 16 位编码(两个八元组)表示任意的 Unicode 代码点,称为 UCS-2 。
此外 UCS-4 是用四个八元组表示代码点。
UCS-2 和 UCS-4 是定长编码(fixed-length encoding) ,直接用编码中字符数乘以每个代码点占用的空间就可以得到文本流占用的最小空间。
显然现在 UCS-2 不足以编码所有 UCS 代码点。现在基于 UCS 的文本编码被标准化为若干 Unicode 传输格式(Unicode transformation Format, UTF) 。
常见的 UTF 主要有 UTF-16 和 UTF-8 。 UTF-16 是 UCS-2 的扩充,使用特别区域的连续两个 16 位值——称为代理对(surrogate pair)——表示 BMP 外的代码点,其它和 UCS-2 兼容。不过这样 UTF-16 就是变长编码(variable-length encoding) 了,不具有定长编码的简便特性。
UTF-8 是稍后提出的变长编码。现行的第三版 UTF-8 被 RFC3629 规范,使用 1~4 个八元组表示 Unicode 代码点。更早的版本可能使用 1~6 个,对于确定上限 U+10FFFF 的情况来说是不必要的。
此外还有 UTF-1 、 UTF-7 、 UTF-EBCDIC 和 UTF-32 (和 UCS-4 功能等价),比较不常用。
5.在现代计算机体系结构中,整数按字节寻址时存储可以有多种形式,存在字节序(endianness) 问题。
一个 16 位的整数典型地可以用两个 8 位的字节表示,这里分为两种情况:高地址存储整数最高位的大端(big-endian) 和低地址存储整数最高位的小端(little-endian) 。
内部存储的字节序一般取决于体系结构和操作系统,如 Windows 和 x86 Linux 使用小端序, PowerPC 使用大端序。
如需要外部传输的编码,就可能需要指定清楚字节序。
UCS-2 和 UTF-16 编码的实现在存储表示上受字节序影响,实际上分为大端和小端版本,即 UCS2-LE 、 UCS2-BE 、 UTF-16LE 和 UTF-16BE 。
UTF-8 编码规范直接指定了八元组序列的存储顺序,所以不用指定字节序。
6.C/C++ 的 wchar_t 类型不指定大小,在不同环境下可以不同,取决于实现。
一般实现在特定的环境下遵循一定的应用程序二进制接口(application binary interface, ABI) ,其中对于基本数据类型的表示有一定要求。因此同一个操作系统下即便语言的实现不同,类型的存储表示一般也是兼容的。
对于 Windows , wchar_t 一般实现为 16 位的小端序整数,可以编码 UCS-2LE 和 UTF-16LE (或者约定存储 BE 版本),但不能直接编码 UCS-4 。
对于 x86 Linux , wchar_t 一般实现为 32 位的小端序整数,可以编码以上各种编码,不过对 UCS-2 显然浪费一半的空间。考虑 UTF-16 流中通常主要是 UCS-2 兼容的字符,浪费空间的概率也很大。
而对于 UTF-8 ,和其它变长编码一样,一般直接用 char 表示最小的编码单位(一个八元组)。
7.鉴于 wchar_t 存在的不足, ISO C11/C++11 引入 char16_t 和 char32_t 分别表示至少 16 位和至少 32 位的用于表示字符的整数类型,以便明确具体编码的存储。
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment