根据我的理解,char
可以安全地存放ASCII字符,而char16_t
和char32_t
可以安全地存储来自unicode的字符,一个用于16位变量,另一个用于32位的变化(我应该说“a”而不是“the”?)。但是我想知道wchar_t
背后的目的是什么。我应该在新代码中使用该类型,还是仅仅支持旧代码?如果根据我的理解,它的大小不能保证大于wchar_t
,那么旧代码中char
的目的是什么?澄清会很好!
答案 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_t
和char32_t
的问题在于它们并不完全受支持,即使在标准C ++库中也是如此:例如,没有直接支持这些类型的流,它比仅实例化流更有用对于这些类型。