C++0x 中 char 和 Unicode 的签名

Posted

技术标签:

【中文标题】C++0x 中 char 和 Unicode 的签名【英文标题】:Signedness of char and Unicode in C++0x 【发布时间】: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

【问题讨论】:

【参考方案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 类型肯定是无符号的。

【讨论】:

以上是关于C++0x 中 char 和 Unicode 的签名的主要内容,如果未能解决你的问题,请参考以下文章

C / C ++如何读取UNICODE的const char?

如何在 C++ 中使用 UTF-8 和 Unicode? C++20 char8_t 有多大?

java 中的 char 数据类型

UNICODE ANSI转换

UNICODE ANSI转换

在C#中如何获得以Unicode格式打印的char的最小值和最大值?