目录

一个字节真能存 255 个字符吗?聊聊字节和字符

字节和字符是两个特别容易混的概念。

很多人写代码处理文本,碰到乱码、截断、长度算错,根子上都在这。

说白了,搞清楚字节、字符、编码这三者的关系,大部分文本处理的坑就能绕开。

字节是什么?

字节(byte)是计算机存储和传输数据的基本计量单位。

一个字节由 8 个比特(bit)组成。

每个比特只有 0 和 1 两种状态,所以一个字节能表示 2^8 = 256 种不同的状态,对应 0 到 255 这 256 个整数。

注意这里的措辞:是「表示 256 种状态」,不是「存 256 个字符」。

字节本身不关心你存的是字符、数字还是图片像素,它只是一串二进制位。

字符是什么?

字符(character)是文字、字母、数字和各种符号的统称。

比如汉字「中」、字母 A、数字 7、标点 ?,甚至空格和换行,都算字符。

字符是给人看的,字节是给机器存的。

两者中间隔着一层东西,叫编码。

字符和字节靠什么连起来?

靠字符编码。

编码规定了「某个字符」对应「哪一串字节」。

输入文本时,把字符转成字节序列,这个过程叫编码(encode)。

输出文本时,把字节序列还原成字符,这个过程叫解码(decode)。

编码和解码用的规则必须一致,否则就乱码。

最常见的乱码场景,就是 UTF-8 编码的内容拿 GBK 去解码,一堆「锟斤拷」就是这么来的。

一个字节能存多少字符?看编码

不同编码下,一个字符占的字节数完全不一样。

下面这张表直接对比:

编码方式 一个字符占用字节 说明
ASCII 1 字节 只覆盖 128 个字符,英文够用
Latin-1 1 字节 西欧语言,扩展到 256 个字符
GBK 1~2 字节 中文常用 2 字节
UTF-8 1~4 字节 变长编码,最通用
UTF-16 2 或 4 字节 常用字符 2 字节
UTF-32 固定 4 字节 不省空间但定位快

所以「一个字节能存多少字符」这个问题,离开编码就没法回答。

ASCII:一个字节存一个字符

ASCII 是最早的字符编码,1967 年定稿。

它只用了一个字节里的低 7 位,能表示 128 个字符(0 到 127)。

包括大小写英文字母、数字、常见标点和一些控制字符。

最高位那一位空着没用,所以一个 ASCII 字符正好用一个字节存。

这也是「一个字节存一个字符」这种说法的来源。

但它只对英文成立。

UTF-8:变长,中文通常 3 字节

UTF-8 是目前互联网上用得最多的编码。

它最大的特点是变长:不同字符占的字节数不一样。

  • ASCII 范围内的字符(英文、数字)仍然只占 1 字节,完全兼容 ASCII
  • 拉丁文带音标、希腊文、西里尔文等占 2 字节
  • 绝大多数常用汉字占 3 字节
  • emoji、生僻字、部分扩展汉字占 4 字节

这里得纠正一个常见的误区:不是「所有中文都占 3 字节」。

基本多文种平面(BMP)内的常用汉字确实是 3 字节,但像「𠮷」这种扩展区汉字,是 4 字节。

emoji 比如「😀」也是 4 字节,有时候渲染上去还是好几个码点拼的,算下来更多。

那「一个字节最多存 255 个字符」对吗?

不对,这是个典型的错误说法。

它把「一个字节能表示 256 种状态」和「能存多少字符」混为一谈了。

256 种状态指的是这个字节能取多少种不同的值,不是能装下多少个字符。

一个字节就是一个字节,它顶多完整存下一个 ASCII 字符。

碰上 UTF-8 的中文,一个字节连半个字都存不下,得三个字节凑一块儿才行。

所以结论很清楚:一个字符要占几个字节,取决于编码;而一个字节能不能存下一个字符,同样取决于编码。

常见问题

Q1. 字节和字符到底有什么区别?

字节是机器存储数据的单位,固定 8 位,能表示 256 种状态。

字符是人能看懂的文字符号。

两者通过字符编码互相转换,一个字符可能占一个或多个字节。

Q2. 为什么一个汉字在 UTF-8 里是 3 个字节?

UTF-8 是变长编码,按字符的 Unicode 码点范围分配字节数。

绝大多数常用汉字的码点落在需要 3 字节表示的区间里。

但生僻字和扩展区汉字会占 4 字节,并非全部都是 3 字节。

Q3. 字符串长度算的是字节还是字符?

看编程语言和方法。

有的语言 len() 算字节数(比如 Go 对字符串直接取长度),有的算字符数(Unicode 码点)。

处理多字节文本时分不清这点,很容易把中文长度算错或者截断出半个字。

Q4. 乱码是怎么产生的?

编码和解码用的规则不一致就会乱码。

比如用 UTF-8 存的文件,拿 GBK 去打开,字节序列被错误地拆分还原,就显示成一堆怪符号。

统一编码(尽量都用 UTF-8)是避免乱码最省事的办法。

小结

字节管存储,字符管表意,编码是它们之间的翻译规则。

「一个字节存一个字符」只在 ASCII 下成立,「一个字节最多存 255 个字符」则纯属误解。

真要回答「一个字节能存几个字符」,先问一句:用的什么编码?

如果你在项目里还碰到过更刁钻的编码坑,比如 BOM 头、UTF-16 大小端之类的,欢迎在评论区聊聊~~~

版权声明

未经授权,禁止转载本文章。
如需转载请保留原文链接并注明出处。即视为默认获得授权。
未保留原文链接未注明出处或删除链接将视为侵权,必追究法律责任!

本文原文链接: https://fiveyoboy.com/articles/byte-and-character/

备用原文链接: https://blog.fiveyoboy.com/articles/byte-and-character/