码位 (Codepoint) - Unicode 中每个字符的地址
最近更新: 2026-05-19·约 3 分钟
本文约 3 分钟读完。
你能输入、粘贴或显示的每一个字符,在 Unicode 中都有一个唯一的地址,称为码位。以 U+ 加十六进制数字的形式表示 (如 U+1F600 对应 😀),码位是计算机存储和传输文本的基础。 理解码位有助于调试 emoji 问题、正确计算字符数,以及编写更好的文本处理代码。
定义
码位是 Unicode 编码空间 (范围从 U+0000 到 U+10FFFF) 中的一个数值。 每个码位恰好映射到一个抽象字符。整个编码空间允许 1,114,112 个码位, 其中约 150,000 个已被分配。
如何读取码位
U+XXXX (或基本多文种平面以上的字符使用 U+XXXXX) 的表示法使用十六进制数字:
- U+0041 = A (拉丁大写字母 A)
- U+3042 = あ (平假名 あ)
- U+1F600 = 😀 (咧嘴笑脸)
- U+1F338 = 🌸 (樱花)
U+0000 到 U+FFFF 范围内的字符位于基本多文种平面 (BMP)。 大多数 emoji 位于 U+FFFF 以上的辅助多文种平面 (SMP),因此在某些编程语言中需要特殊处理。
码位 vs. 字符 vs. 字形
| 概念 | 含义 | 示例 |
|---|---|---|
| 码位 | 编号 (地址) | U+1F600 |
| 字符 | 抽象概念 | 「咧嘴笑脸」 |
| 字形 | 视觉呈现 | 😀 (因平台而异) |
emoji 码位对开发者的重要性
字符串长度的意外
在 JavaScript 中,"😀".length 返回 2 而不是 1。 这是因为 JavaScript 字符串使用 UTF-16 编码,U+FFFF 以上的 emoji 需要 一个代理对 (两个 16 位编码单元)。要正确计数字符,可以使用:
[..."😀"].length→ 1 (展开为码位数组)new Intl.Segmenter()用于字素簇计数
数据库存储
MySQL 的 utf8 字符集每个字符最多支持 3 字节 (仅 BMP)。 emoji 需要 4 字节,因此必须使用 utf8mb4 才能无损存储。 PostgreSQL 的 text 类型原生支持所有 Unicode。
正则表达式
在正则中匹配 emoji 需要 Unicode 感知的模式。 JavaScript 中:/\p{Emoji}/u 可匹配任何 emoji 字符。 如果不加 u 标志,代理对将无法正确匹配。
查找字符的码位
- 浏览器 DevTools:
"🌸".codePointAt(0).toString(16)→ "1f338" - Python:
hex(ord("🌸"))→ "0x1f338" - 命令行:
printf '%x\n' "'🌸" - 在线工具:Unicode Charts 可按区块浏览
emoji 创作中的码位
在制作 emoji 组合时,了解码位可以帮助你:
- 找出字符显示为空白方块的原因 (不支持的码位)
- 区分来自不同区块但外观相似的字符
- 调试复制粘贴时不可见字符 (ZWJ、变体选择符) 被去除的问题
- 在按码位计数的平台上计算组合的真实「成本」
相关术语
- ZWJ (零宽连接符) - 用于组合 emoji 的不可见字符