char16_t、unsigned short 和 UTF-16之间的关系

53 阅读3分钟

char16_t、unsigned short 和 UTF-16 之间有密切的关系:

  1. 定义和大小:
// 这三种类型在大多数系统上都是16位
static_assert(sizeof(char16_t) == 2, "char16_t must be 16 bits");
static_assert(sizeof(unsigned short) == 2, "unsigned short must be 16 bits");
  1. 关系说明:
  • char16_t:

    • C++11引入的类型
    • 专门用于表示UTF-16编码的字符
    • 保证16位大小
    • 类型安全,语义明确
  • unsigned short:

    • 传统C/C++类型
    • 通常是16位
    • 常用来存储UTF-16编码
    • 平台可能有差异
  • UTF-16:

    • 一种Unicode编码方式
    • 使用16位或32位(代理对)表示字符
    • 基本平面字符用16位表示
    • 扩展平面字符用代理对(32位)表示
  1. 使用示例:
// 不同表示方式的等价性
char16_t c1 = u'你';
unsigned short c2 = 0x4F60;  // "你"的UTF-16编码
  1. 转换示例:
// 类型转换
char16_t* str1 = u"Hello";
unsigned short* str2 = (unsigned short*)str1;

// UTF-16编码处理
void process_utf16(const char16_t* str) {
    while (*str) {
        if (*str >= 0xD800 && *str <= 0xDBFF) {
            // 处理代理对
            char16_t high = *str++;
            char16_t low = *str++;
            // 计算实际Unicode码点
            int codepoint = ((high - 0xD800) << 10) + 
                           (low - 0xDC00) + 0x10000;
        } else {
            // 基本平面字符
            int codepoint = *str++;
        }
    }
}
  1. 实际应用:
// 字符串转换函数
std::string utf16_to_utf8(const char16_t* input) {
    std::string output;
    while (*input) {
        char16_t ch = *input++;
        
        if (ch < 0x80) {
            // ASCII
            output += static_cast<char>(ch);
        }
        else if (ch < 0x800) {
            // 2字节UTF-8
            output += static_cast<char>(0xC0 | (ch >> 6));
            output += static_cast<char>(0x80 | (ch & 0x3F));
        }
        else if (ch >= 0xD800 && ch <= 0xDBFF) {
            // 处理代理对
            char16_t high = ch;
            char16_t low = *input++;
            int codepoint = ((high - 0xD800) << 10) + 
                           (low - 0xDC00) + 0x10000;
            
            // 4字节UTF-8
            output += static_cast<char>(0xF0 | (codepoint >> 18));
            output += static_cast<char>(0x80 | ((codepoint >> 12) & 0x3F));
            output += static_cast<char>(0x80 | ((codepoint >> 6) & 0x3F));
            output += static_cast<char>(0x80 | (codepoint & 0x3F));
        }
        else {
            // 3字节UTF-8
            output += static_cast<char>(0xE0 | (ch >> 12));
            output += static_cast<char>(0x80 | ((ch >> 6) & 0x3F));
            output += static_cast<char>(0x80 | (ch & 0x3F));
        }
    }
    return output;
}
  1. 区别要点:
  • 类型安全:

    char16_t* str1 = u"Hello";  // 明确的UTF-16字符串
    unsigned short* str2;       // 可能是任何16位数据
    
  • 编译器支持:

    // char16_t支持字面量前缀
    char16_t* str = u"你好";  // UTF-16字面量
    
  • 平台兼容性:

    #ifdef _WIN32
    typedef wchar_t utf16_char;  // Windows
    #else
    typedef char16_t utf16_char; // 其他平台
    #endif
    
  1. 最佳实践:
// 现代C++推荐使用char16_t
void process_text(const char16_t* text) {
    // UTF-16处理
}

// 处理遗留代码
void legacy_function(const unsigned short* text) {
    // 转换为char16_t处理
    const char16_t* modern_text = reinterpret_cast<const char16_t*>(text);
    process_text(modern_text);
}

总结:

  • char16_t是专门为UTF-16设计的类型
  • unsigned short常用于旧代码中表示UTF-16
  • 两者在大多数情况下可以互换使用
  • 推荐在新代码中使用char16_t
  • UTF-16编码可以用这两种类型存储