Unicode 支持需要 wchar_t 吗?
Posted
技术标签:
【中文标题】Unicode 支持需要 wchar_t 吗?【英文标题】:Is wchar_t needed for unicode support? 【发布时间】:2011-01-16 14:28:02 【问题描述】:Unicode 支持需要wchar_t
类型吗?如果不是,那么这种多字节类型的意义何在?当您可以使用 char
完成相同的事情时,为什么还要使用 wchar_t?
【问题讨论】:
相关:***.com/questions/1613494/why-was-wchar-t-invented 【参考方案1】:char
通常是一个字节。 (sizeof(char)
必须等于 1)。
wchar_t
被添加到语言中,专门用于假设多字节字符。
【讨论】:
“字节”的 C 和 C++ 定义是“单个字符占用的内存量”。这里不需要像“一般”这样的黄鼠狼世界。它可能不是一个 octet(8 位)。【参考方案2】:wchar_t 不是必需的。甚至不能保证有特定的编码。关键是要提供一种数据类型来表示系统原生的宽字符,类似于表示原生字符的 char。例如,在 Windows 上,您可以使用 wchar_t 访问宽字符 Win32 API 函数。
【讨论】:
【参考方案3】:因为你不能用char
完成同样的事情:
The Absolute Minimum Every Software Developer Absolutely, Positively Must Know About Unicode and Character Sets (No Excuses!)
【讨论】:
正如那篇文章的标题所说,这是每个开发人员绝对、肯定必须了解的有关 unicode 的知识。仅出于这个原因,我希望我能给予不止一个支持。 :) 参考是好的,但这个说法实际上是非常错误的。使用 UTF-8 将 Unicode 映射到旧版char
不仅是可能的,而且很可能是最常见的单一编码。
zdawg 是对的。您不需要 wchar_t 来正确实现 Unicode,使用它甚至不一定有帮助。一方面,wchar_t 可以小到 8 位。在 Windows 上它是 16,这意味着您可以表示 UTF-16 代码单元,但 /not all charaters/。这就是为什么 Unicode 标准说“因此,需要在任何 C 或 C++ 编译器之间移植的程序不应该使用 wchar_t 来存储 Unicode 文本。”您可以使用 char,只要您将 char 视为“字节”的意思。
-1 wchar 是值得发明的东西之一,因为 wchar_t 可能是 4 或 2 个字节。【参考方案4】:
wchar_t
绝对不是 Unicode 所必需的。例如,UTF-8 保持与 ASCII 的向后兼容性并使用普通的 8 位 char
。 wchar_t
主要支持所谓的多字节字符,或者基本上任何使用超过sizeof(char)
编码的字符集。
【讨论】:
这听起来像是在暗示 UTF-8 将所有字符编码为 8 位,这不仅不正确,而且如果为真,那将是数据压缩的一项壮举。 UTF-8 是一种多字节编码:有些字符使用8位编码,有些使用16位,有些使用24位,有些使用32位。它可以支持(尽管我认为目前不需要)使用最多 48 位编码的字符。 “听起来你在暗示 UTF-8 将所有字符编码为 8 位”——不,它没有。 "wchar_t
主要支持所谓的多字节字符" - 您将 "multi-byte" 与 “可变宽度”。 “可变宽度” 是 UTF-8 和 UTF-16 的固有特性。那里没有区别。此外,C++ 标准不要求对wchar_t
进行任何特定编码。编译器可以选择将其设为 UTF-32,从而产生 固定 宽度的字符编码。这个答案相当具有误导性,完全没有用。 -1.
@DanMoulding 听起来你拿了一件东西,然后决定通过添加它来代表别人说话,这样你就可以批评原来的观点了。这不仅不合理,而且是谬误。不,答案根本不暗示这一点。是您希望它成为或相信它是或任何其他可能性。但这实际上并没有包含在答案中。
@DanMoulding 我知道。但是您仍然阅读的内容超出了答案的内容。如果我的评论被认为是恶意的,我深表歉意——这不是故意的。我天生就是一个讽刺的人,虽然我尽了最大的努力,但有时我并不清楚。你试图增加清晰度很好。事实上,这很棒。我只是认为暗示该帖子暗示其他内容是不正确或不公平的。无论如何,如果我引起了冒犯,我很抱歉 - 这并不是什么意思,而是要指出一个不幸的是太普遍的谬误,即阅读超出预期的内容(我们也都容易受到影响)。【参考方案5】:
请注意,wchar_t 通常为 16 位,不足以存储所有 unicode 字符,并且是 UTF_8 中数据的错误选择
【讨论】:
这在 Linux(或者,我假设其他 Unix-ish 系统)上是不正确的,它是 32 位的。这取决于编译器和运行时。 @greyfade 说wchar_t
“不足以存储所有Unicode字符”的重点是该程序没有可移植获得固定宽度的简单性用它编码。【参考方案6】:
没有。
从技术上讲,没有。 Unicode 是一种定义代码点的标准,它不需要特定的编码。
因此,您可以将 unicode 与 UTF-8 编码一起使用,然后所有内容都可以放入一个或一个短序列 char
对象中,它甚至仍会以空值结尾。
UTF-8 和 UTF-16 的问题在于 s[i]
不再是一个字符,它可能只是一个字符,而对于足够宽的字符,您可以保留 s[i]
的抽象概念单个字符,但它不会在各种转换下使 strings 固定长度。
32 位整数的宽度至少足以解决代码点问题,但它们仍然不能处理极端情况,例如,向上转换可以改变字符数。
所以事实证明x[i]
问题即使是char32_t 也没有完全解决,而且那些其他编码会导致文件格式很差。
那么,您的暗示是非常有效的:wchar_t
是失败的,部分原因是 Windows 仅将其设为 16 位,部分原因是它没有解决所有问题,并且与字节流抽象非常不兼容。
【讨论】:
Unicode 仅在最近(4.0?)添加了超过 65536 个代码点。因此,符合标准的 C++ 实现必须选择:仅支持 Unicode 3.x 和 16 位wchar_t
,或使用 32 位 wchar_t
。使用 UTF-16 在技术上是不符合标准的,因为没有“null-null-terminated multi-wchar_t”编码这样的东西。
BMP 之外的字符于 2001 年首次在 Unicode 3.1 中分配。
“UTF-8 的问题在于......” IMO 这根本不是问题。另一方面,wchar_t 的问题在于,它给人一种错误的错觉,即这种 one-wchar_t-equals-one-UNICODE 字符抽象在显然不是这种情况时仍然适用。这只会促进有缺陷的代码在程序必须处理违反此错误假设的字符时崩溃。
“UTF-8 的问题”与 UTF-16 的问题完全相同。您的回答给人的印象是,在某些系统中是 16 位的 wchar 在这方面问题较少。没有中间地带可以“大部分保留”抽象——您要么正确处理 UTF-16 代理对,要么不正确处理,在这种情况下,您的程序将被破坏。
好的,我已经更新了一些内容,以记录各种固定长度编码尝试的渐进式失败。我之前的描述是准确的,因为固定长度的编码确实工作了一段时间,但人们没有得到隐含的时间线。【参考方案7】:
您绝对不需要wchar_t
来支持软件中的 Unicode,实际上使用wchar_t
会更加困难,因为您不知道“宽字符串”是 UTF-16 还是 UTF-32 - 这取决于在操作系统上:在 windows 下 utf-16 所有其他 utf-32。
但是,utf-8 让您可以轻松编写支持 Unicode 的软件(*)
见:https://***.com/questions/1049947/should-utf-16-be-considered-harmful
(*) 注意:在 Windows 下,您仍然必须使用 wchar_t
,因为它不支持 utf-8 语言环境,因此对于启用 unicode 的 Windows 编程,您必须使用基于 wchar 的 API。
【讨论】:
【参考方案8】:如前所述,对于 unicode 支持,wchar_t 绝对不是必需的。不仅如此,它也完全没有用,因为该标准没有为 wchar_t 提供固定大小的保证(换句话说,您不提前知道特定系统上的 sizeof( wchar_t ) 是多少),而 sizeof( char ) 将始终为 1。
在 UTF-8 编码中,任何实际的 UNICODE 字符都映射到一个或多个(我相信最多四个)八位字节的序列。 在 UTF-16 编码中,任何实际的 UNICODE 字符都映射到一个或多个(我相信最多两个)16 位字的序列。 在 UTF-32 编码中,任何实际的 UNICODE 字符都被映射到一个 32 位字。
如您所见,wchar_t 可用于实现 UTF-16 支持 IF 该标准足以保证 wchar_t 始终为 16 位宽。不幸的是它没有,所以无论如何你都必须从<cstdint>
(例如std::uint16_t)恢复为固定宽度的整数类型。
<slightly OffTopic Microsoft-specific rant>
更令人气愤的是微软的 Visual Studio UNICODE 和 MBCS(多字节字符集)构建配置造成的额外混乱。这两个都是
A) 令人困惑和 B) 一个彻头彻尾的谎言
因为 Visual Studio 中的“UNICODE”配置并没有为程序员购买实际的 Unicode 支持做任何事情,这两种构建配置所暗示的差异也没有任何意义。为了解释,微软建议使用 TCHAR 而不是直接使用 char 或 wchar_t。在 MBCS 配置中,TCHAR 扩展为 char,这意味着您可以使用它来实现 UTF-8 支持。在 UNICODE 配置中,它扩展为 wchar_t,它在 Visual Studio 中恰好是 16 位宽,并且可能用于实现 UTF-16 支持(据我所知,这是 Windows 使用的本机编码) .但是,两种这些编码都是多字节字符集,因为 UTF-8 和 UTF-16 都允许将特定 Unicode 字符分别编码为多个字符/wchar_t ,所以术语多字节字符集(相对于单字节字符集?)意义不大。
雪上加霜,仅仅使用 Unicode 配置实际上并不能为您提供一点 Unicode 支持。要真正做到这一点,您必须使用真正的 Unicode 库,例如 ICU (http://site.icu-project.org/)。简而言之,wchar_t 类型以及 Microsoft 的 MBCS 和 UNICODE 配置并没有增加任何用处并造成不必要的混乱,如果它们都没有被发明出来,世界将会变得更加美好。
</slightly OffTopic Microsoft-specific rant>
【讨论】:
以上是关于Unicode 支持需要 wchar_t 吗?的主要内容,如果未能解决你的问题,请参考以下文章