冲突:C ++标准和Windows实现中wchar_t字符串的定义?

时间:2010-12-08 03:39:18

标签: c++ unicode c++11 string-literals wchar-t

  

来自c ++ 2003 2.13

     

宽字符串文字的类型为“ n const wchar_t 的数组”并且具有静态存储持续时间,其中n是下面定义的字符串的大小

     

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

     

来自c ++ 0x 2.14.5

     

宽字符串文字的类型为“数组n const wchar_t ”,其中n是字符串的大小,如下所示

     

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

     

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

C ++ 2003中的陈述非常模糊。但是在C ++ 0x中,当计算字符串的长度时,宽字符串文字wchar_t应被视为与char32_t相同,并且与char16_t不同。

有一篇文章明确说明了Windows如何在https://stackoverflow.com/questions/402283?tab=votes%23tab-top

中实现wchar_t

简而言之,Windows中的wchar_t是16位并使用UTF-16编码。标准中的陈述显然在Windows中留下了一些冲突。

例如,

wchar_t kk[] = L"\U000E0005";

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

但是,从标准来看,kk是2 wchar_t的数组(通用名称\ U000E005为1,\ 0为1)。

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

这显然是相互冲突的。

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

我的理解有什么不对吗?

感谢。

2 个答案:

答案 0 :(得分:4)

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

BMP之外的字符很少使用,Windows本身在内部使用UTF-16编码,因此VC ++以这种方式运行简单方便(即使不正确)。但是,而不是"禁止"这些字符,wchar_t的大小可能会在将来增加而char16_t在Windows API中占据一席之地。

你所链接的答案也有些误导:

  

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

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

答案 1 :(得分:2)

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

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