7

从 c++2003 2.13

宽字符串文字的类型为“<strong>array of n const wchar_t”并具有静态存储持续时间,其中 n 是字符串的大小,定义如下

宽字符串文字的大小是转义序列、通用字符名称和其他字符的总数,加上终止 L'\0' 的数量。

从 c++0x 2.14.5

宽字符串文字的类型为“<strong>array of n const wchar_t”,其中 n 是字符串的大小,定义如下

char32_t 或宽字符串文字的大小是转义序列、通用字符名称和其他字符的总数,加上终止 U'\0' 或 L'\0' 的数量。

char16_t 字符串文字的大小是转义序列、通用字符名称和其他字符的总数,每个需要代理对的字符加一个,终止 u'\0' 加一个。

C++2003 中的声明相当模糊。但在 C++0x 中,计算字符串长度时,宽字符串字面量 wchar_t 应与 char32_t 相同,与 char16_t 不同。

在https://stackoverflow.com/questions/402283?tab=votes%23tab-top中有一篇文章清楚地说明了 windows 如何实现 wchar_t

简而言之,windows 中的 wchar_t 是 16 位,使用 UTF-16 编码。标准中的声明显然在 Windows 中留下了一些冲突的东西。

例如,

wchar_t kk[] = L"\U000E0005";

这超过了 16 位,对于 UTF-16,它需要两个 16 位来对其进行编码(代理对)。

但是,根据标准,kk 是 2 个 wchar_t 的数组(1 代表通用名称 \U000E005,1 代表 \0)。

但在内部存储中,Windows 需要 3 个 16 位 wchar_t 对象来存储它,2 个 wchar_t 用于代理对,1 个 wchar_t 用于 \0。因此,从数组的定义来看,kk 是一个包含 3 个 wchar_t 的数组。

这显然是相互矛盾的。

我认为 Windows 的一个最简单的解决方案是“禁止”任何需要 wchar_t 中的代理对的东西(“禁止”BMP 之外的任何 unicode)。

我的理解有什么问题吗?

谢谢。

4

2 回答 2

4

该标准要求wchar_t足够大以容纳支持的字符集中的任何字符。基于此,我认为您的前提是正确的——VC++\U000E0005使用两个wchar_t单位表示单个字符是错误的。

BMP 之外的字符很少使用,而且 Windows 本身内部使用 UTF-16 编码,因此 VC++ 以这种方式表现非常方便(即使不正确)。然而,与其“禁止”这样的字符,wchar_t未来的大小可能会增加,同时char16_t在 Windows API 中占据一席之地。

您链接到的答案也有些误导:

在 Linux 上,awchar_t是 4 字节,而在 Windows 上,它是 2 字节

的大小wchar_t完全取决于编译器,与操作系统无关。恰好 VC++ 使用 2 个字节来表示wchar_t,但再一次,这在未来很可能会发生变化。

于 2010-12-08T06:53:19.143 回答
2

Windows 对 wchar_t 一无所知,因为 wchar_t 是一个编程概念。相反,wchar_t 只是存储,它对您存储在其中的数据的语义值一无所知(也就是说,它对 Unicode 或 ASCII 什么的一无所知。)

如果针对 Windows 的编译器或 SDK 将 wchar_t 定义为 16 位,则该编译器可能与 C++0x 标准冲突。(我不知道是否有一些 get-out 子句允许 wchar_t 为 16 位。)但无论如何编译器都可以将 wchar_t 定义为 32 位(以符合标准)并提供运行时函数以转换为/from UTF-16 用于当您需要将 wchar_t* 传递给 Windows API 时。

于 2010-12-08T07:49:11.000 回答