char vs wchar_t vs char16_t vs char32_t(c ++ 11)

时间:2013-09-28 15:52:38

标签: c++ c++11

根据我的理解,char可以安全地存放ASCII字符,而char16_tchar32_t可以安全地存储来自unicode的字符,一个用于16位变量,另一个用于32位的变化(我应该说“a”而不是“the”?)。但是我想知道wchar_t背后的目的是什么。我应该在新代码中使用该类型,还是仅仅支持旧代码?如果根据我的理解,它的大小不能保证大于wchar_t,那么旧代码中char的目的是什么?澄清会很好!

2 个答案:

答案 0 :(得分:51)

char用于8位代码单元,char16_t用于16位代码单元,char32_t用于32位代码单元。其中任何一个都可以用于'Unicode'; UTF-8使用8位代码单元,UTF-16使用16位代码单元,UTF-32使用32位代码单元。


wchar_t所做的保证是,语言环境中支持的任何字符都可以从char转换为wchar_t,并且char使用的是任何表示形式,无论如何多个字节,移位代码,你有什么,wchar_t将是一个单一的,不同的值。这样做的目的是,您可以操纵wchar_t字符串,就像使用ASCII的简单算法一样。

例如,将ascii转换为大写如下:

auto loc = std::locale("");

char s[] = "hello";
for (char &c : s) {
  c = toupper(c, loc);
}

但是这不会处理将UTF-8中的所有字符转换为大写,或者转换为其他一些编码的所有字符,如Shift-JIS。人们希望能够像这样将这些代码国际化:

auto loc = std::locale("");

wchar_t s[] = L"hello";
for (wchar_t &c : s) {
  c = toupper(c, loc);
}

所以每个wchar_t都是一个'字符',如果它有一个大写版本,那么它可以直接转换。不幸的是,这并不是真的有效;例如,在某些语言中存在奇怪之处,例如德语字母ß,其中大写版本实际上是两个字符SS而不是单个字符。

因此,国际化的文本处理本质上比ASCII更难,并且不能像wchar_t的设计者那样真正简化。因此wchar_t和宽字符通常没什么价值。

使用它们的唯一原因是它们已经融入了一些API和平台。但是,即使在这样的平台上进行开发,我也希望在我自己的代码中坚持使用UTF-8,并且只需在API边界处转换为所需的编码。

答案 1 :(得分:20)

当Unicode承诺创建16位表示时,类型wchar_t被置于标准中。大多数供应商选择使wchar_t 32位,但一家大型供应商选择将其设为16位。由于Unicode使用超过16位(例如,20位),因此我们认为我们应该有更好的字符类型。

char16_t的意图是表示UTF16,而char32_t意味着直接表示Unicode字符。但是,在使用wchar_t作为其基本界面一部分的系统上,您将遇到wchar_t。如果你不受约束,我会亲自使用char来表示使用UTF8的Unicode。 char16_tchar32_t的问题在于它们并不完全受支持,即使在标准C ++库中也是如此:例如,没有直接支持这些类型的流,它比仅实例化流更有用对于这些类型。