为什么C ++ 11引入了char16_t和char32_t类型

时间:2014-01-21 16:41:08

标签: c++ c++11 types

为什么C ++ 11 Standard引入了char16_tchar32_t类型?是不是1字节足以存储字符?扩展字符类型的大小有什么用途吗?

3 个答案:

答案 0 :(得分:9)

因此,在您阅读了Joel关于Unicode的文章之后,您应该了解一般的Unicode,而不是C ++。

C ++ 98的问题在于它真的不知道Unicode。 (除了通用字符引用转义语法之外。)C ++只需要实现来定义“基本源字符集”(这基本上没有意义,因为它是关于源文件的编码,因此归结为告诉编译器“这是“)”,“基本执行字符集”(由窄字符串表示的一些字符集,以及用于在运行时表示它的8位(可能是多字节)编码,必须包含最重要的字符)在C ++中)和“宽执行字符集”(基本集的超集,以及使用wchar_t作为其代码单元的编码,需要单个{{1} }可以表示集合中的任何字符。)

这些字符集中的实际值都没有。

那发生了什么?

好吧,微软很早就转向了Unicode,当它仍然只有不到2 ^ 16个字符时。他们使用UCS-2实现了他们的整个NT操作系统,UCS-2是旧Unicode版本的固定宽度16位编码。他们将其宽泛的执行字符集定义为Unicode,使wchar_t 16位并使用UCS-2编码非常有意义。对于基本集,他们选择“无论当前的ANSI代码页是什么”,这没有任何意义,但他们几乎继承了这一点。由于窄字符串支持被认为是遗留的,因此Windows API充满了奇怪的限制。我们会谈到这一点。

Unix转换了一会儿,当时已经很清楚16位还不够。面对使用16位可变宽度编码(UTF-16),32位固定宽度编码(UTF-32 / UCS-4)或8位可变宽度编码(UTF-8)的选择,与UTF-8一起使用,它也具有很好的属性,即用于处理ASCII和ISO-8859- *文本的大量代码甚至不需要更新。对于wchar_t,他们选择32位和UCS-4,以便它们可以在一个单元中表示每个Unicode代码点。

微软随后将他们拥有的所有内容升级为UTF-16以处理新的Unicode字符(带有一些长期存在的错误),并且由于向后兼容性,wchar_t仍为16位。当然,这意味着wchar_t不能再代表单个单元中的广泛集合中的每个字符,使得Microsoft编译器不符合要求,但没有人认为这是一个大问题。它不像某些C ++标准API完全依赖于该属性。 (嗯,是的,wchar_t是。运气好。)

但是,他们仍然认为UTF-16是可行的方式,狭窄的API仍然是不受欢迎的继子女。 UTF-8没有得到支持。您不能将UTF-8与狭窄的Windows API一起使用。您无法使Microsoft编译器使用UTF-8作为窄字符串文字的编码。他们只是觉得不值得。

结果:尝试为Unix和Windows编写国际化应用程序时极度痛苦。 Unix可以与UTF-8,UTF-16的Windows一起使用。它很丑。 codecvt在不同的平台上有不同的含义。

wchar_tchar16_t以及新的字符串文字前缀char32_tuU是尝试为程序员提供可靠的工具使用编码。当然,您仍然需要为多平台代码进行奇怪的编译时切换,或者决定一个编码并在某个包装层进行转换,但至少您现在拥有适合后一种选择的正确工具。想要去UTF-16路线吗?在任何地方使用u8u,根据需要在系统API附近转换为UTF-8。以前你在Unix环境中完全不能这样做。想要UTF-8吗?使用char16_tchar,在UTF-16系统API附近进行转换(并避免使用标准库I / O和字符串操作,因为Microsoft的版本仍然不支持UTF-8)。以前在Windows中根本无法做到这一点。现在你甚至可以使用UTF-32,如果你真的想要转换到任何地方。在Windows之前,这也是不可能的。

这就是为什么这些东西都在C ++ 11中:给你一些工具来解决可怕的SNAFU围绕跨平台代码中的字符编码,至少在某种程度上可预测和可靠的方式。

答案 1 :(得分:7)

1个字节从来就不够用。存在数百种Ansi 8bit编码,因为人们不断尝试将不同语言填充到8位限制的范围内,因此相同的字节值在不同语言中具有不同的含义。然后Unicode来解决这个问题,但它需要16位(UCS-2)。最终,世界语言的需求超过了16位,因此创建了UTF-8/16/32编码来扩展可用值。

创建了

char16_tchar32_t(以及它们各自的文本前缀),以便在所有平台上以统一的方式处理UTF-16/32。最初,有wchar_t,但它是在Unicode是新的时创建的,它的字节大小从未标准化,甚至直到今天。在某些平台上,wchar_t为16位(UTF-16),而在其他平台上则为32位(UTF-32)。多年来,当跨平台交换Unicode数据时,这引起了大量的互操作性问题。 char16_tchar32_t最终被引入标准尺寸 - 分别为16位和32位 - 以及所有平台上的语义。

答案 2 :(得分:0)

在Unicode中定义了大约100000个字符(它们称为代码点)。所以为了指定其中任何一个,1个字节是不够的。 1个字节就足以枚举它们中的前256个,这恰好与ISO-8859-1相同。两个字节足以用于最重要的Unicode子集,即所谓的 Basic Multilingual Plane ,以及许多应用程序,例如Java,支持Unicode的16位字符。如果你想要真正的每一个Unicode字符,你必须超越它并允许4字节/ 32位。由于不同的人有不同的需求,C ++允许不同的大小。 UTF-8是程序中很少使用的可变大小编码,因为不同的字符长度不同。在某种程度上,这也适用于UTF-16,但在大多数情况下,您可以使用char16_t安全地忽略此问题。