以下是我的2014年标准草案N4140
的一些摘录22.5标准代码转换方面[locale.stdcvt]
3对于三个代码转换方面
codecvt_utf8
,codecvt_utf16
和codecvt_utf8_utf16
中的每一个: (3.1) -Elem
是宽字符类型,例如wchar_t
,char16_t
或char32_t
。4对于方面
codecvt_utf8
:
(4.1) - 方面应在程序内转换UTF-8多字节序列和UCS2或UCS4(取决于Elem
的大小)。
这两段的一种解释是wchar_t
必须编码为UCS2或UCS4。我不喜欢它,因为如果它是真的,我们在图书馆描述深处埋藏了一种重要的语言属性。我试图找到一个更直接的声明这个属性,但无济于事。
wchar_t
编码不需要是UCS2或UCS4的另一种解释,以及在{0}} codecvt_utf8
不适合wchar_t
工作的实现。我也不喜欢这种解释,因为如果它是真的,并且char
和wchar_t
本机编码都不是Unicode,那么它似乎不是一种方式可以在这些本机编码和Unicode之间进行便携式转换。
这两种解释中哪一种是正确的?还有一个我忽略了吗?
澄清我不会询问有关wchar_t
是否适合软件开发的一般意见,或wchar_t
可以从其他地方获得的属性。我对标准的这两个特定段落感兴趣。我试图了解这些特定段落带来或不带来的含义。
澄清2 。如果4.1表示&#34; facet将在UTF-8多字节序列和UCS2或UCS4 之间转换,或者当前全局语言环境对wchar_t施加的任何编码&#34;没有问题。它没有。它说的是什么。看来如果使用std::codecvt_utf8<wchar_t>
,最终会有一堆wchar_t
编码为UCS2或UCS4,而不管当前的全局区域设置如何。 (无法为codecvt_utf8
)指定区域设置或任何字符转换方面。所以这个问题可以这样重写:转换结果是否可以直接用于当前的全局语言环境(和/或任何可能的语言环境),用于输出,wctype
查询等等?如果没有,那么可用于? (如果上面的第二种解释是正确的,答案似乎是&#34;没有&#34;)。
答案 0 :(得分:6)
wchar_t
只是一个完整的字面值。它有最小值,最大值等。
其尺寸不受标准规定。
如果足够大,您可以将UCS-2或UCS-4数据存储在wchar_t
的缓冲区中。无论您使用何种系统,都是如此,因为UCS-2和UCS-4以及UTF-16和UTF-32只是序列中排列的整数值的描述。
在C ++ 11中,有std
个API可以读取或写入数据,假设它具有这些编码。在C ++ 03中,有些API使用当前语言环境读取或写入数据。
22.5标准代码转换方面[locale.stdcvt]
3对于三个代码转换方面中的每一个,codecvt_utf8,codecvt_utf16和codecvt_utf8_utf16:
(3.1) - Elem是宽字符类型,例如wchar_t,char16_t或char32_t。
4对于facet codecvt_utf8:
(4.1) - 方面应在程序内转换UTF-8多字节序列和UCS2或UCS4(取决于Elem的大小)。
所以这里codecvt_utf8_utf16
一方面处理utf8
,另一方面处理UCS2或UCS4(取决于Elem有多大)。它确实转换。
Elem(宽字符)被假定为在UCS2或UCS4中编码,具体取决于它的大小。
这并不意味着wchar_t
被编码,只是意味着此操作将wchar_t
解释为编码为。
UCS2或UCS4如何进入Elem并不是标准所关心的部分。也许你用十六进制常量设置它。也许你是从io中读到的。也许你是在飞行中计算出来的。也许你使用了一个高质量的随机数发生器。也许你将ascii
字符串的位值加在一起。也许你计算了月亮将地球日改变1秒所需的秒数的log*
的定点近似值。 不是这些段落的问题。这些段落只是强制要求如何修改和解释位。
在其他情况下也有类似的说法。这并不强制wchar_t
具有哪种格式。它只是说明了这些方面如何解释wchar_t
或char16_t
或char32_t
或char8_t
(阅读或写作)。
与wchar_t
交互的其他方式使用不同的方法来强制解释wchar_t
的值。
iswalpha
使用(全局)区域设置来解释wchar_t
。在某些本地人中,wchar_t
可能是UCS2。在其他情况下,它可能是一些疯狂的cthulian编码,其细节使您能够从空间中看到新的颜色。
要明确:编码不是数据或位的属性。编码是数据解释的属性。通常只有一个正确的或合理的数据解释,但数据本身就是位。
C ++标准不强制要求wchar_t
中存储的内容。它确实要求某些操作解释wchar_t
的内容。该部分描述了某些方面如何解释wchar_t
中的数据。
答案 1 :(得分:5)
没有
a:hover {
color: green;
}
只需要保存编译器支持的最大语言环境。从理论上讲,它可以适用于char。
类型wchar_t是一种不同的类型,其值可以表示支持的语言环境(22.3.1)中指定的最大扩展字符集的所有成员的不同代码。
- C ++ [basic.fundamental] 3.9.1 / 5
因此它甚至不需要支持Unicode
wchar_t的宽度是特定于编译器的,可以小到8位。因此,需要可以在任何C或C ++编译器上移植的程序不应使用wchar_t来存储Unicode文本。 wchar_t类型用于存储编译器定义的宽字符,在某些编译器中可能是Unicode字符。
ISO / IEC 10646:2003 Unicode标准4.0
答案 2 :(得分:3)
让我们区分使用wchar_t
前缀构建的L
和字符串文字。
wchar_t
只是一个整数类型,可能大于char
。
使用L
前缀的字符串文字将使用wchar_t
个字符生成字符串。究竟是什么意味着依赖于实现。不要求此类文字使用任何特定编码。他们可能会使用UTF-16,UTF-32或其他与Unicode无关的东西。
因此,如果您希望在所有平台上以Unicode格式编码保证的字符串文字,请使用u8
,u
或{{1}字符串文字的前缀。
这两段的一种解释是wchar_t必须编码为UCS2或UCS4。
不,这不是一个有效的解释。 U
没有编码;它只是一种类型。它是数据,它被编码。前缀为wchar_t
的字符串文字可能会也可能不会在UCS2或UCS4中编码。
如果您提供L
一串codecvt_utf8
个字符串,这些字符串在UCS2或UCS4中编码(适用于wchar_t
),那么它将起作用。但不是因为sizeof(wchar_t)
;它只能起作用,因为你提供的数据是正确编码的。
如果4.1表示“该方面应在UTF-8多字节序列和UCS2或UCS4之间进行转换,或者当前全局语言环境对wchar_t施加的任何编码”都没有问题。
这些wchar_t
方面的重点是执行与区域设置无关的转换。如果您想要与区域设置相关的转换,则不应使用它们。您应该使用全局codecvt_*
方面。
答案 3 :(得分:1)
Microsoft列出了您的第一个结论,他们列举了可能的选项,并注意到UTF-16虽然“广泛用作[sic]”但不是有效的编码。
QNX也使用了相同的措辞,它指出了措辞的来源:QNX和Microsoft都从Dinkumware派生了他们的标准库实现。
现在,正如它发生的那样,Dinkumware也是引入这些类的N2401的作者。所以我要支持他们。
答案 4 :(得分:1)
由于Elem
可以是wchar_t
,char16_t
或char32_t
,因此第4.1条没有说明所需的wchar_t
编码。它说明了所执行的转换。
根据措辞,很明显转换是在UTF-8和UCS-2或UCS-4之间,具体取决于Elem
的大小。因此,如果wchar_t
是16位,则转换将使用UCS-2,如果是32位,则转换为UCS-4。
为什么标准提到UCS-2和UCS-4而不是UTF-16和UTF-32?因为codecvt_utf8
会将多字节UTF8转换为单个宽字符:
codecvt_utf8
)虽然,我不清楚会发生什么,如果UTF-8文本包含的序列对应于用于接收{0}的UCS-2中不可用的unicode字符。
答案 5 :(得分:1)
你的解释都不正确。标准并不要求只有一个wchar_t
编码,就像它不需要单char
个编码一样。 codecvt_utf8
方面必须在UTF-8和UCS-2或UCS-4之间进行转换。
在任何语言环境中,不支持UTF-8,UCS-2和UCS-4作为字符集。
如果Elem
的类型为wchar_t
并且不足以存储UCS-2值,则codecvt_utf8
方面的转换操作未定义,因为标准没有说明那种情况会发生什么。如果它足够大(或者如果你想证明标准要求它必须足够大)那么它只是实现定义UCS-2或UCS-4 wchar_t
值是否生成了facet生成或使用的编码与定义wchar_t
编码的任何区域设置兼容。
答案 6 :(得分:0)
第一种解释是有条件的。
如果定义了__STDC_ISO_10646__
宏(从C导入),则wchar_t
是某个版本的Unicode的超集。
__STDC_ISO_10646__
yyyymmL
形式的整数文字(例如,199712L
)。如果定义了这个符号,那么每一个 Unicode所需集中的字符,当存储在类型为wchar_t
的对象中时,具有相同的值 作为该角色的短标识符。 Unicode必需集包含所有字符 由ISO / IEC 10646定义,以及所指定的所有修正和技术勘误 年和月。
似乎如果定义了宏,可以假设某种UCS4。 (不是UCS2,因为ISO 10646从未有过16位版本; ISO 10646的第一个版本对应于Unicode 2.0)。
因此,如果定义了宏,那么
codecvt_utf8<wchar_t>
提供的转换与此原始编码兼容如果未定义宏,则不需要保留这些内容。
还有__STDC_UTF_16__
和__STDC_UTF_32__
,但C ++标准没有说出它们的含义。 C标准表示它们分别表示char16_t
和char32_t
的UTF-16和UTF-32编码,但在C ++中,这些编码总是被使用。
顺便提一下,函数mbrtoc32
和c32rtomb
在char
序列和char32_t
序列之间来回转换。在C中,如果定义了__STDC_UTF_32__
,它们只使用UTF-32,但在C ++中,UTF-32始终用于char32_t
。因此,即使__STDC_ISO_10646__
未定义,也应该可以通过从UTF-8转换为UTF-32来在UTF-8和wchar_t
之间进行转换。将char32_t
编码为原生编码char
到本机编码wchar_t
,但我害怕这些复杂的东西。