【问题标题】:Why was wchar_t invented?为什么要发明 wchar_t?
【发布时间】:2010-12-09 11:13:47
【问题描述】:

为什么需要wchar_t?它比short(或__int16 或其他)有什么优势?

(如果重要的话:我生活在 Windows 世界中。我不知道 Linux 为支持 Unicode 做了什么。)

【问题讨论】:

标签: c++ c windows


【解决方案1】:

Wikipedia

基本上,它是当前语言环境中“文本”的可移植类型(带有变音符号)。它早于 Unicode,并没有解决很多问题,所以今天,它主要是为了向后兼容而存在的。除非必要,否则不要使用它。

【讨论】:

  • 阿门。事实上,完全转储 ANSI 语言环境的东西。将所有文本视为 utf8(如果需要,可以转换输入)并使用标准 C 库函数。这是在 C 中做 I18N 的唯一明智的方法。
  • Nemanja, Michael Kaplan 是一位多产的作家。您能否更具体地说明要搜索的内容?
  • 这是相当错误的,但我无法准确确定。 2个简单的反例说明了很多。在 Windows 上,wchar_t aka WCHAR 的通用编码是 UTF-16,它 (A) 不是特定于语言环境的 (B) 绝对是基于 Unicode 的。在 Mac OSX 上,wchar_t 只保存 Unicode 代码点。因此,绝对不是为了向后兼容,这就是两个最常见的桌面操作系统支持 Unicode 的方式。
  • Unicode != UTF-8。 unicode 的大多数实现也在内部使用 16 位字符,因为否则许多操作不会有效。所以 wchar_t 可能是 Unicode 的老祖宗。
  • @Martin Beckett:我想你指的是 Windows 的 UTF-16 WCHAR。一个 32 位的wchar_t 显然支持所有的 unicode 字符。 UTF-16 也是如此,尽管 BMP 集之外的字符需要 2 个 WCHAR(4 个字节)。谷歌术语:“高低代理”。对于中文/日文/韩文,UTF-16 比 UTF-8 更有效(大多数 CJK 表意文字在 UTF-8 中占用 3 个字节)
【解决方案2】:

为什么需要 wchar_t?它如何优于 short(或 __int16 或其他)?

在 C++ 世界中,wchar_t 是它自己的类型(我认为它是 C 中的 typedef),因此您可以基于此重载函数。例如,这可以输出宽字符,而 not 可以输出它们的数值。在 VC6 中,wchar_t 只是 typedefunsigned short,这段代码

wchar_t wch = L'A'
std::wcout << wch;

会输出65,因为

std::ostream<wchar_t>::operator<<(unsigned short)

被调用。在较新的 VC 版本中,wchar_t 是一个独特的类型,所以

std::ostream<wchar_t>::operator<<(wchar_t)

被调用,并输出A

【讨论】:

  • 顺便说一句:可以在新 VC 的项目设置中禁用此行为(您不应该,但可能需要向后兼容)
【解决方案3】:

存在wchar_t 的原因与存在size_ttime_t 的原因几乎相同 - 它是一种抽象,指示类型要表示的内容并允许实现选择可以表示的底层类型特定平台上的正确类型。

请注意,wchar_t 不需要是 16 位类型 - 有些平台是 32 位类型。

【讨论】:

  • 请注意,在 C++ 中,wchar_t 是内置类型(如 char),而 size_t 和 time_t 是 typedef。
  • @rdb 你知道使它成为内置类型的理由是什么吗?
  • @PSkocik 使它成为一个内置类型使得它可以重载函数,这样你就可以进行不同的重载接受 wchar_t 并且任何整数类型恰好在大小上与 @987654326 重叠@。 C 没有重载,所以不需要。
【解决方案4】:

通常认为给数据类型这样的东西有意义的名字是一件好事。

什么是最好的,char 还是 int8?我认为:

char name[] = "Bob";

比这更容易理解:

int8 name[] = "Bob";

wchar_tint16 也是一样的。

【讨论】:

  • wchar_t 的大小并不总是与 int16 相同。它是一种宽度因平台而异的类型,不幸的是......
  • 这就是 C++0x 引入 char16_t 和 char32_t 的原因,因此您可以显式使用 UTF16 或 UCS4,同时仍保留字符语义。
【解决方案5】:

当我阅读相关标准时,微软似乎把这个标准搞砸了很糟糕

我的 POSIX 手册页 &lt;stddef.h&gt; 说:

  • wchar_t:整数类型,取值范围可以 代表不同的宽字符 指定的最大字符集的所有成员的代码 编译环境支持的语言环境:null 字符的代码值为 0 并且 可移植字符集的每个成员的代码值等于 用作整数字符中的唯一字符时的值 常数。

因此,如果您的平台支持 Unicode,那么 16 位 wchar_t 是不够的。每个 wchar_t 都应该是一个字符的不同值。因此,wchar_t 从一种在文本字符级别工作的有用方式(当然,在从语言环境多字节解码之后)变成了在 Windows 平台上完全无用的方式。

【讨论】:

  • 我认为这不是微软实现的问题,而是 C++ 规范并没有真正考虑到 Unicode。 Unicode 中的字符集是什么? wchar_t 是否必须能够表示所有 Unicode 代码点,或者只是所有代码 units?在UTF16的情况下,一个代码单元是一个16位的整数,所有这些都可以用微软的wchar_t来表示。
  • 我认为宽字符串 (L"blah") 在 Windows 上是 UTF-16 编码的。因此它能够表示完整的 Unicode,但它是一种多字节编码(至少对于某些 Unicode 字符而言)。 ICBWT。
  • 如果是多字节编码,那么它的“值范围”不能真正为字符集的所有成员保存不同的值,可以吗?
  • @jalf - wchar_t 的重点是将多字节编码解码为一个简单的表示,每个数组位置都有一个字符。 Windows 上指定的最大字符集是 Unicode。 UTF-16 不是字符集,它是 Unicode 的编码。
  • 什么是“字符”?即使你有一个 32 位的 wchar_t,组合形式的存在意味着你的字符串可能使用多个代码点来表示用户认为的单个字符。
【解决方案6】:

wchar_t 是用于存储和处理平台的 unicode 字符的原语。它的大小并不总是 16 位。在 unix 系统上,wchar_t 是 32 位的(也许 unix 用户更可能使用额外位用于的克林贡字符:-)。

这可能会给移植项目带来问题,尤其是如果您将wchar_t 和short 互换,或者如果您将wchar_t 和xerces' XMLCh 互换。

因此,将wchar_t 作为与short 不同的类型对于编写跨平台代码非常重要。清理这是将我们的应用程序移植到 unix,然后从 VC6 到 VC2005 的最困难的部分之一。

【讨论】:

  • 顺便说一句,UNIX 程序经常跳过wchar_t,大部分时间将文本表示为 UTF-8 :)
  • 我知道如果我再次重做我们的应用程序,我会更喜欢 utf-8 而不是 ucs-16/utf16。
【解决方案7】:

补充 Aaron 的评论 - 在 C++0x 中,我们终于获得了真正的 Unicode 字符类型:char16_t 和 char32_t 以及 Unicode 字符串文字。

【讨论】:

    【解决方案8】:

    从某种意义上说,它是“高级”的,它允许您分隔上下文:您在字符上下文(如字符串)中使用wchar_t,在数字上下文(数字)中使用short。现在,编译器可以执行类型检查来帮助您捕捉错误地将一种与另一种混合在一起的情况,例如将shorts 的抽象非字符串数组传递给字符串处理函数。

    作为一个边节点(因为这是一个 C 问题),在 C++ 中,wchar_t 允许您独立于 short 重载函数,即再次提供适用于字符串和数字的独立重载(例如)。

    【讨论】:

    • +1 指出 wchar_t 可以独立于 short 或 int 进行重载。
    【解决方案9】:

    wchar_t 有点像 unicode 标准化之前的遗留问题。不幸的是,它不是很有帮助,因为编码是特定于平台的(在 Solaris 上,是特定于语言环境的!),并且没有指定宽度。此外,无法保证 utf-8/16/32 编解码器方面将可用,或者您将如何访问它们。一般来说,便携式使用有点像噩梦。

    显然 c++0x 将支持 unicode,但以目前的进展速度可能永远不会发生......

    【讨论】:

      【解决方案10】:

      除了一个小的ISO 2022 japanese minority,wchar_t 总是 unicode。如果你真的很着急,你可以在编译时确定:

      #ifndef __STDC_ISO_10646__
      #error "non-unicode wchar_t, unsupported system"
      #endif
      

      有时 wchar_t 是 16 位 UCS-2 有时是 32 位 UCS-4,那又如何呢?只需使用sizeof(wchar_t)。 wchar_t 不打算发送到磁盘或网络,它只打算在内存中使用。

      另请参阅此网站上的Should UTF-16 be considered harmful?

      【讨论】:

      • __STDC_ISO_10646__ 表示 wchar_t 的值与 Unicode 码位的值相同。该条件不适用于 Unicode 编码 UTF-16 和 UTF-8,但它确实适用于 ASCII 和 UCS-2。
      • 无论__STDC_ISO_10646__ 说什么 wchar_t 都不应该存储 UTF-16(或任何其他编码形式),这明显违反了上面引用的 POSIX 标准。存储 UCS-2 即可。在不关心标准的平台上,所有赌注都失败了。
      • 这不是那么简单。如果您指的是引用说支持的语言环境中最大字符集中的所有字符都由不同的 wchar_t 值表示,则不排除 UTF-16 不排除 UCS-2;只要没有语言环境支持非 BMP 字符,那么如果这些非 BMP 字符不是由不同的 wchar_t 值表示的,那么从技术上讲,这不是违规行为。当然,如果对字符的语言环境支持是唯一的支持,那么您将无法区分,但事实并非如此。
      • 几乎整个 wchar.h API 都是基于语言环境的;所以在语言环境之外使用 wchar_t 听起来真的很疯狂。另外,当给定半个 UTF-16 字符输入时,像 wctomb() 这样的函数应该如何表现?抱歉,wchar_t 中的 UTF-16 对它的滥用实在是太严重了。这实际上一定是为什么这个线程中的所有 Windows 开发人员似乎都讨厌它。
      • Windows' 提供了自己的wchar_t API,不限于当前 C 或 C++ 语言环境支持的字符。 wctomb() 仅定义为处理语言环境支持的字符,语言环境支持的字符需要由不同的wchar_t 值表示。只要没有语言环境支持 BMP 之外的任何字符,那么技术上就不会违反标准。我不会争辩说 UTF-16 不是滥用和违反 wchar_t 的精神,只是说它在技术上并不违反规范的文字。
      猜你喜欢
      • 2020-01-08
      • 1970-01-01
      • 2011-05-06
      • 2019-08-26
      • 2019-11-12
      • 1970-01-01
      • 2014-11-08
      • 2020-12-09
      • 1970-01-01
      相关资源
      最近更新 更多