【问题标题】:char vs wchar_t vs char16_t vs char32_t (c++11)char vs wchar_t vs char16_t vs char32_t (c++11)
【发布时间】:2013-10-04 19:30:23
【问题描述】:

据我了解,char 可以安全地容纳 ASCII 字符,而 char16_tchar32_t 可以安全地容纳 unicode 字符,一个用于 16 位品种,另一个用于 32 位品种(我应该说“a”而不是“the”吗?)。但是我想知道wchar_t 背后的目的是什么。我应该在新代码中使用该类型,还是只是为了支持旧代码? wchar_t 在旧代码中的目的是什么,据我了解,如果它的大小不能保证大于 char?澄清一下就好了!

【问题讨论】:

    标签: c++ c++11


    【解决方案1】:

    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 将是一个单一的、不同的值。这样做的目的是,您可以像使用 ASCII 的简单算法一样操作 wchar_t 字符串。

    例如,将 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 边界处转换为所需的任何编码。

    【讨论】:

    • 我喜欢你的评论和库尔的评论,他们都有独特的信息。我希望我能给两张绿色支票。我得考虑一下才能决定谁得到它。是否是 stackoverflow 上的标准协议,在出现平局时不进行检查?
    • “德语字母 ß 的大写版本实际上是两个字符 SS” - 这不太准确。 “ß”的大写版本是“ẞ”(U+1E9E:拉丁大写字母 Sharp S)。它是在 Unicode 5.1 中引入的(参见 Tailored Casing Operations 以供参考)。虽然默认的 Unicode 大小写将大写“ß”转换为“SS”,但这确实不是大写版本。
    • @IInspectable 使用“SS”并不是 Unicode 大小写算法的发明。以实际使用为准。使用“SS”和“SZ”是常见的做法,Unicode 算法旨在尊重这一点。从您链接到的 Unicode 文档中,“特别是,大写的 s 用于标识和大写标题的印刷表示,以及用户要求将 s 保留为大写的其他环境。总体而言,这种用法很少见。”
    • @IInspectable 但是你是对的,从技术上讲,“ß”没有传统的大写字母,“SS”或“SZ”的使用源于“ss”或“sz”的使用“ß”字符不可用(例如,使用缺少“ß”键的键盘书写德语时)。由于传统上没有大写 ß,因此实践是将常用的“ss”和“sz”替代物大写以获得“ß”的大写形式。
    • ß 传统上没有大写字母,因为它不是字母,而是传统小写字母 s(在 fraktur 中写为竖线)和小写字母 z 的连字。这就是为什么它被称为 esszet 是德语。 Unicode 5.1 引入的大写“ẞ”仅用于标题大小写。实际文本中的大写永远不会使用它。
    【解决方案2】:

    当 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++ 库中也不支持:例如,没有直接支持这些类型的流,而且它比仅仅为这些类型实例化流更有效。

    【讨论】:

    • 标准中缺乏对char16_tchar32_t 的支持是因为标准声明没有此类支持,还是因为类型是新的,这意味着支持会随着时间的推移而出现?
    • @user904963:当前修订版不要求为char16_tchar32_t 版本命名。然而,它似乎确实规定了必要的方面,这意味着可以使用流。我没有看到改进支持的提案,但这并不意味着委员会反对增加支持,也就是说,它可能会到来。
    • 完整的 char16_t 和 char32_t 支持从未到来。
    猜你喜欢
    • 2016-03-11
    • 2014-07-25
    • 1970-01-01
    • 1970-01-01
    • 2011-11-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多