【问题标题】:Signedness of char and Unicode in C++0xC++0x 中 char 和 Unicode 的签名
【发布时间】:2011-01-24 09:04:35
【问题描述】:

在 C++0x 工作草案中,用于处理 Unicode 的新字符类型(char16_tchar32_t)将是无符号的(uint_least16_t uint_least32_t 将是基础类型)。

但据我所知(也许不是很远)类型 char8_t(基于 uint_least8_t)没有定义。为什么 ?

当您看到为 UTF-8 字符串文字引入了新的 u8 编码前缀时,这更加令人困惑......基于老朋友 (sign/unsigned) char强>。为什么?

更新: 有一个添加新类型的提议:char8_t

char8_t:UTF-8 字符和字符串的类型(修订版 1) http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2018/p0482r1.html

【问题讨论】:

    标签: c++ unicode utf-8 char c++11


    【解决方案1】:

    char 将是用于 UTF-8 的类型,因为它被重新定义以确保它可以与它一起使用:

    为了加强支持 对于 C++ 编译器中的 Unicode, char 类型的定义是 修改为至少大小 需要存储一个八位编码 UTF-8 和大到足以容纳 编译器基本的任何成员 执行字符集。它是 以前只定义为后者。 共有三种 Unicode 编码 C++0x 将支持:UTF-8、UTF-16 和 UTF-32。除了之前的 注意到定义的变化 char, C++0x 将添加两个新字符 类型:char16_t 和 char32_t。这些 旨在存储 UTF-16 和 分别为 UTF-32。

    来源:http://en.wikipedia.org/wiki/C%2B%2B0x

    大多数 UTF-8 应用程序已经在 PC/mac 上使用 char。

    【讨论】:

    • 没有说签名。
    • 为什么粗体部分的措辞很尴尬? “UTF-8的八位编码”不是多余的吗?
    • 嗯,这就是维基百科,措辞经常变化,而且质量差异很大。但是我没有找到另一个总结这些 un​​icode 相关功能的来源。
    【解决方案2】:

    char16_tchar32_t 应该可用于表示代码点。由于没有负代码点,因此将它们无符号是明智的。

    UTF-8 不直接表示代码点,所以u8 的底层类型是否有符号无关紧要。

    【讨论】:

    • 如果我想存储字符 é (U+00E9),也就是两个字节序列 0xC3 0xA9,带有一个有符号字符数组,它将失败:signed char e_acute = {0xC3,0xA9} => 这将截断值。因此,如果您的系统将 char 定义为带符号的 char,它仍然是一个问题。我错了吗?
    • 克里斯,是否可以保证unsigned char -> signed char -> unsigned char 这对转换将产生原始值?前一个转换是实现定义的,我找不到任何可以保证往返的子句。
    • 我的意思是,如果您从某个地方接收 UTF-8 数据(作为 0--255 范围内的数字序列,这是 UTF-8 的定义方式),您不能可靠地将它们存储在 char 数组中,因为通过转换回 unsigned char 获得的值可能不同(我什至不确定 CHAR_BIT 是否保证至少为 8)。为了可靠性,你必须使用uint_least8_t,在我看来,为它提供char8_t typedef 似乎有用且一致。
    • 不,你永远不会直接解释 UTF8。您将其传递给运行时支持函数,该函数将其转换为本机字符类型,如 wchar_t。所以你把它放在什么样的字节包中并不重要。
    • 将 UTF-8 文件读入有符号字符缓冲区也会产生同样的问题。此外,如果您的 char 已签名,则不能假定 std::string (basic_string) 是有效的 UTF-8 字符串。即使使用 u8,我也看不出这是如何变化的?
    【解决方案3】:

    C++0x 草案似乎没有说明新的 Unicode 字符类型是有符号还是无符号。但是,正如其他人已经提到的那样,由于没有负 Unicode 代码点,因此将 char16_tchar32_t 无符号会更有意义。 (话又说回来,char 无符号是有道理的,但自 70 年代以来我们一直在处理“负”字符。)

    此外,由于 UTF-16 的范围从 0x0 到 0xFFFF(忽略代理对),您需要一个无符号 16 位整数的整个范围才能正确表示所有值。至少可以说,如果代码点 0x8000 到 0xFFFF 用char16_t 表示为负数,那会很尴尬。

    无论如何,在 C++0x 委员会就此事发表明确意见之前,您始终可以检查您的实现:

    #include <type_traits>
    #include <iostream>
    
    int main()
    {
        std::cout << std::boolalpha << std::is_signed<char16_t>::value << std::endl;
    }
    

    这会在 Linux 上使用 GCC 4.45 打印出 false。所以至少在一个平台上,新的 Unicode 类型肯定是无符号的。

    【讨论】:

      猜你喜欢
      • 2011-06-09
      • 1970-01-01
      • 2010-10-26
      • 1970-01-01
      • 2011-06-11
      • 2014-02-04
      • 1970-01-01
      • 2012-04-22
      相关资源
      最近更新 更多