为什么 Unicode 有大端或小端而 UTF-8 没有?

为什么 Unicode 有大端或小端而 UTF-8 没有?

UNICODE 一个字符使用 2 个字节,因此有大端序和小端序之分。例如,字符“哈”是54 C8十六进制的。因此,它的 UTF-8 为:

11100101 10010011 10001000

UTF-8 使用 3 个字节来表示同一个字符,但是它没有大端或小端之分。为什么?

答案1

注意:由于历史原因,Windows 使用“Unicode”一词来表示 UCS-2 - 最初那是仅有的将 Unicode 代码点编码为字节的方法,因此区别并不重要。但在现代术语中,两个都示例是 Unicode,但第一个具体是 UCS-2 或 UTF-16,第二个是 UTF-8。

UCS-2 有大端和小端,因为它直接将代码点表示为 16 位“uint16_t”或“短整型”数字,就像在 C 和其他编程语言中一样。它与其说是一种“编码”,不如说是数值的直接内存表示,而且 uint16_t 在不同机器上可以是 BE 或 LE,UCS-2 也是如此。后来的 UTF-16 只是为了兼容性而继承了同样的混乱。

(可能可以已经针对特定的字节序进行了定义,但我猜他们觉得这超出了范围,或者必须在代表不同硬件制造商的人员之间做出妥协。我不知道实际的历史。)

同时,UTF-8 是可变长度编码,可以使用 1 到 6 个字节来表示 31 位值。字节表示与 CPU 架构完全无关;相反有一个特定的算法将数字编码为字节,反之亦然。无论在哪种 CPU 上运行,该算法始终以相同的顺序输出或使用位。

答案2

这与字节数组(char[]在 C 语言或byte[]许多其他语言中)没有关联的字节顺序,但其他类型的数组却有关联的字节顺序完全相同byte。这是因为字节顺序将由多个字节表示的值存储到内存中的方式。如果只有一个字节,则只有一种方法将其存储到内存中。但是,如果一个int由 4 个字节组成,索引为 1 到 4,则可以按多种不同的顺序存储它,例如 [1, 2, 3, 4]、[4, 3, 2, 1]、[2, 1, 4, 3]、[3, 1, 2, 4]... 即小端、大端、混合端...

Unicode 有很多不同的编码称为Unicode 转换格式其中主要的有 UTF-8、UTF-16 和 UTF-32。UTF-16 和 UTF-32 适用于16 位和 32 位单位显然,当你将 2 个或 4 个字节存储到字节寻址内存中时,你必须定义要读取/写入的字节的顺序。UTF-8 OTOH 适用于字节单位,因此不存在字节顺序

答案3

UTF-8 使用 3 个字节来表示同一个字符 [哈54 C8],但是它没有大端或小端之分。为什么?

原因(或可能的解释)是这三个字节对代码点位的编码与 UTF-16 不同:

UTF-8    11100101 10010011 10001000    E5 93 88
         1110xxxx 10xxxxxx 10xxxxxx
             0101   010011   001000    54 C8

代码点(01010100 11001000[哈54 C8])的 16 位分布在 UTF-8 字节流中的三个字节中(第一个字节和两个连续字节)。

根据编码规则,最高有效位始终位于最左边。这样就可以从最低字节索引到最高字节索引逐字节解析 UTF-8。

比较:UTF-8(D92 UTF-8 编码形式 - 3.9 Unicode 编码形式,Unicode 14.0.0 p.123)

代码点的数量在计算机内存中的存储方式不受此影响。

对于 UTF-16 来说,情况就不那么清楚了,因为 UTF-16 可能建议逐字(而不是逐字节)读取字节流。因此,一个字内字节顺序的含义(以及位的顺序)可能会有所不同:

UTF-16BE    01010100 11001000    54 C8
UTF-16LE    11001000 01010100    C8 54

如果您现在将流中的单词映射到计算机内存中,则需要对架构进行匹配以获取代码点值。

另请参阅:大端字节序和小端字节序的区别

答案4

字节序列没有字节序。想想 ASCII 字符串,它由许多字节组成,但没有字节序。只有当多个字节形成一个实体时才有字节序,因为您可以按任意方式对字节进行排序以形成该实体。UTF-8 不会将 Unicode 字符编码为多字节实体,而是将其编码为字节序列,而 UTF-16 将 Unicode 字符编码为 16 位值的实体,这意味着每个实体都有两个字节,并且可以按一种方式或另一种方式排序。

相关内容