从 UTF8 转换为 UTF16 LE C 编程中的数学运算的概念

标签 c embedded

我想知道从UTF8到UTF16 LE转换的概念

例如 输入序列 E3 81 82 输出序列为 42 30

此转换中实际的算术运算是什么。(我不想调用内置库)

最佳答案

基本上,Unicode 是一种在一个连续的代码空间中表示尽可能多的符号的方法,每个符号的代码通常称为“代码点”。 UTF-8UTF-16 只是用一个或多个八位字节 (UTF-8) 或 16 位字 (UTF-16) 编码和表示这些代码点的方法),最新的可以表示为little-endian(“最低有效优先”或“英特尔字节顺序”)或big-endian(“最重要的第一”,或“摩托罗拉字节顺序”)序列,这给了我们两个变体:UTF-16LE和UTF-16BE。

首先您需要做的是从 UTF-8 序列中提取代码点。 UTF-8编码如下:

0x00...0x7F“按原样”编码符号,它对应于标准 ASCII 符号

但是,如果设置了最高有效位(即0x80...0xFF),则意味着这是一个由多个字节组成的序列,它们一起对代码点进行编码

范围 0xC0...0xFF 中的字节位于该序列的第一个位置,以二进制表示形式,它们将是:

  • 0b110xxxxx - 后面还有 1 个字节,xxxxx 是代码点的 5 个最高有效位
  • 0b1110xxxx - 接下来还有 2 个字节,xxxx 是代码点的 4 个最高有效位
  • 0b11110xxx - 还有 3 个字节...
  • 0b111110xx - 还有 4 个字节...

Unicode 标准中没有定义代码点,目前需要超过 5 个 UTF-8 字节。

以下字节来自0x80...0xBF范围(即0b10xxxxxx),并对代码点值的接下来的六位(从最高有效位到最低有效位)进行编码。

所以,看看你的例子:E3 81 82

  • 0xE3 == 0b11100011 表示此代码点中将多出 2 个字节,0011 - 是其中的最高有效位
  • 0x81 == 0b10000001 表示这不是代码点序列中的第一个字节,它编码接下来的 6 位:000001
  • 0x82 == 0b10000010 表示这不是代码点序列中的第一个字节,它编码接下来的 6 位:000010

即结果将是 0011 000001 000010 == 0x3042

UTF-16 的工作方式相同。大多数常见的代码点只是“按原样”编码,但一些大值被打包在所谓的“代理对”中,它们是两个 16 位字的组合:

  • 0xD800...0xDBFF范围内的值代表其中的第一个,其低 10 位对结果代码点的 10 个最高有效位进行编码。
  • 0xDC00...0xDFFF范围内的值表示第二个,其较低位对结果代码点的 10 个最低有效位进行编码。

大于 0xFFFF(显而易见)的值和 0xD800...0xDFFF 的值需要代理项对 - 但此范围在代理项对的 Unicode 标准中保留,并且不能有此类符号。

因此,在我们的示例中 0x3042 未达到该范围,因此只需要一个 16 位字。

由于在您的示例中给出了 UTF-16LE(小端)变体,这意味着在字节序列中,第一个将是该单词的最低有效一半。即

0x42 0x30

关于从 UTF8 转换为 UTF16 LE C 编程中的数学运算的概念,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56149244/

相关文章:

rust - 如何在 Rust 的特定内存区域中声明静态变量?

embedded - 测试实时操作系统的硬度

c - 在嵌入式 MCU 应用程序中,在 for 循环中使用 uint_fast16_t 还是 size_t 更好?

c++ - 将纯lua对象传递给C函数并获取值

c - unsigned long long 十六进制格式打印

接受连接后打开两个线程时,C 无限循环中断并出现代码 141

c - 使用 char 和 int 访问内存映射寄存器的区别

c - 具有不同迭代的循环

c - scanf 的异常行为

c - 从文本中读取数字并对数字进行排序