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 位值的实体,这意味着每个实体都有两个字节,并且可以按一种方式或另一种方式排序。