C语言无外部库实现UTF8四字节转UTF16(已有三字节转换宏)
UTF-8四字节转UTF-16的C语言实现(无外部库)
背景说明
你已定义了三字节UTF-8转UCS-16的宏(注意C语言宏名不能包含减号,以下修正为合法命名):
#define UTF8_3BYTE_TO_UCS16(char1, char2, char3) \ ((((char1) & 0x0F) << 12) | (((char2) & 0x3F) << 6) | ((char3) & 0x3F))
四字节UTF-8对应Unicode辅助平面(U+10000~U+10FFFF),无法用单个UCS-16码元表示,需转换为UTF-16代理对(高代理码元+低代理码元),以下是实现方案:
核心实现逻辑
四字节UTF-8转UTF-16的步骤:
- 从四字节UTF-8序列解码出Unicode码点
- 将码点转换为UTF-16代理对:
- 计算偏移量:
码点 - 0x10000 - 高代理码元:
0xD800 | (偏移量 >> 10) - 低代理码元:
0xDC00 | (偏移量 & 0x3FF)
- 计算偏移量:
宏定义实现
以下宏可直接将四字节UTF-8序列转换为UTF-16代理对,结果存入指定变量:
#include <stdint.h> #define UTF8_4BYTE_TO_UTF16(char1, char2, char3, char4, high_surrogate, low_surrogate) \ do { \ uint32_t codepoint = (((char1) & 0x07) << 18) | (((char2) & 0x3F) << 12) | (((char3) & 0x3F) << 6) | ((char4) & 0x3F); \ uint32_t offset = codepoint - 0x10000; \ (high_surrogate) = (uint16_t)(0xD800 | (offset >> 10)); \ (low_surrogate) = (uint16_t)(0xDC00 | (offset & 0x3FF)); \ } while(0)
宏的细节说明
- 使用
do-while(0)包裹是为了保证宏在各种语句块中都能正常使用,避免语法错误 - 依赖
<stdint.h>提供的uint32_t/uint16_t,保证跨平台的类型一致性 - 需确保输入的四字节是合法UTF-8序列:首字节范围
0xF0~0xF7,其余字节范围0x80~0xBF
使用示例
#include <stdio.h> #include <stdint.h> // 修正后的三字节转UCS16宏 #define UTF8_3BYTE_TO_UCS16(char1, char2, char3) \ ((((char1) & 0x0F) << 12) | (((char2) & 0x3F) << 6) | ((char3) & 0x3F)) // 四字节转UTF16代理对宏 #define UTF8_4BYTE_TO_UTF16(char1, char2, char3, char4, high_surrogate, low_surrogate) \ do { \ uint32_t codepoint = (((char1) & 0x07) << 18) | (((char2) & 0x3F) << 12) | (((char3) & 0x3F) << 6) | ((char4) & 0x3F); \ uint32_t offset = codepoint - 0x10000; \ (high_surrogate) = (uint16_t)(0xD800 | (offset >> 10)); \ (low_surrogate) = (uint16_t)(0xDC00 | (offset & 0x3FF)); \ } while(0) int main() { // 示例:U+1F600(笑脸emoji)的UTF-8编码:0xF0 0x9F 0x98 0x80 uint8_t utf8_4byte[] = {0xF0, 0x9F, 0x98, 0x80}; uint16_t high, low; UTF8_4BYTE_TO_UTF16(utf8_4byte[0], utf8_4byte[1], utf8_4byte[2], utf8_4byte[3], high, low); printf("UTF-16代理对:0x%04X 0x%04X\n", high, low); // 输出:0xD83D 0xDE00(对应U+1F600的UTF-16编码) return 0; }
额外注意事项
- 实际转换时需先判断UTF-8序列的长度:通过首字节的高位标识判断(单字节:0xxxxxxx;双字节:110xxxxx;三字节:1110xxxx;四字节:11110xxx)
- 要处理非法UTF-8序列(如截断字节、格式错误的后续字节),避免未定义行为
内容的提问来源于stack exchange,提问作者JInu Thomas
相关产品推荐
相关产品推荐

