核心答案:ASCII 用 7 位表示 128 个英文字符;Unicode 为全球每个字符分配唯一码点(如「中」= U+4E2D);UTF-8 是 Unicode 的存储方案,用 1-4 个变长字节——英文 1 字节、中文 3 字节、emoji 4 字节。三者关系:Unicode 定字符编号,UTF-8 定字节存储,ASCII 是二者共同的子集。
三套标准是什么关系
| 标准 | 解决什么 | 容量 | 单位 |
|---|---|---|---|
| ASCII(1963) | 英文字符数字化 | 128 个 | 7 位(1 字节) |
| Unicode(1991) | 全球字符统一编号 | 1,114,112 码点 | 码点(编号,非字节) |
| UTF-8(1993) | Unicode 的字节存储 | 同 Unicode | 变长 1-4 字节 |
关键区分:码点 ≠ 字节。码点是逻辑编号(「中」永远是 U+4E2D),字节是物理存储(UTF-8 下是 E4 B8 AD 三个字节,GBK 下是 D6 D0 两个字节)。
常用码点速查表
| 字符 | ASCII/Unicode 码点 | UTF-8 字节 |
|---|---|---|
| A | 65 / U+0041 | 1 字节:41 |
| a | 97 / U+0061 | 1 字节:61 |
| 0 | 48 / U+0030 | 1 字节:30 |
| 空格 | 32 / U+0020 | 1 字节:20 |
| 中 | — / U+4E2D | 3 字节:E4 B8 AD |
| © | — / U+00A9 | 2 字节:C2 A9 |
| 😀 | — / U+1F600 | 4 字节:F0 9F 98 80 |
UTF-8 字节数怎么算
规则(码点 → 字节数):
- U+0000–U+007F(0-127)→ 1 字节(与 ASCII 完全一致)
- U+0080–U+07FF → 2 字节(拉丁扩展、希腊、西里尔)
- U+0800–U+FFFF → 3 字节(绝大多数汉字在这里)
- U+10000–U+10FFFF → 4 字节(emoji、生僻字)
估算公式:一段纯中文 UTF-8 文本的字节数 ≈ 字数 × 3。
实例:中文「中」的三层表示
- 字符层:中
- 码点层:U+4E2D(十进制 20013)——Unicode 规定的唯一编号
- 字节层(UTF-8):
E4 B8 AD——4E2D 落在 U+0800-U+FFFF 区间 → 3 字节,按1110xxxx 10xxxxxx 10xxxxxx模板填入 16 位码点得 11100100 10111000 10101101
用 [Unicode 码点查询](/c/dev/unicode) 输入任意字符即可看到码点与 UTF-8/UTF-16 字节分解。
实例:emoji 为什么占 2 个长度
JavaScript 里 「😀」.length === 2——因为 JS 字符串按 UTF-16 码元计数,U+1F600 超出基本平面(U+FFFF),需一对代理(surrogate pair)= 2 个码元。遍历字符串请用 [...str] 或 for...of(按码点迭代),否则 emoji 会被切成乱码半块。
常见误区
- 「Unicode 就是 UTF-8」:Unicode 是编号表,UTF-8/UTF-16/UTF-32 才是存储方案。说「转成 Unicode」通常指拿到码点。
- 「中文一定 2 字节」:那是 GBK。UTF-8 下中文是 3 字节;数据库 varchar(10) 在 utf8mb4 下按字符计,但老 MySQL 的 utf8 只支持 3 字节存不下 emoji——这正是 utf8mb4 存在的原因。
- 「乱码是数据坏了」:99% 是声明不符。文件按 UTF-8 存、编辑器按 GBK 读 → 锟斤拷。把读取编码改对,数据分文未损。
- 「摩斯码是编码」:摩斯码是信号的时序表示(点·划−),不是字节编码;SOS = ···−−−···,与 ASCII/Unicode 完全两个体系——它是前数字时代的遗产。