我见过C++社区中的很多人(特别是freenode上的## c ++)对windows api 的使用wstrings和使用感到不满wchar_t.究竟是什么"错误"有wchar_t和wstring,如果我要支持国际化,有一些什么替代宽字符?
wchar_t- 用于宽字符表示的类型(请参阅宽字符串).要求足够大以表示任何支持的字符代码点(在支持Unicode的系统上为32位.一个值得注意的例外是Windows,其中wchar_t是16位并且保存UTF-16代码单元)它具有相同的大小,签名和对齐作为整数类型之一,但是是一个不同的类型.
Type
wchar_t是一种不同的类型,其值可以表示支持的语言环境中指定的最大扩展字符集的所有成员的不同代码.类型wchar_t应具有与其他整数类型相同的大小,符号和对齐要求,称为其基础类型.类型char16_t和char32_t表示不同类型与大小相同,符号性,和对准如uint_least16_t和uint_least32_t,分别在<cstdint>,称为基础类型.
所以,如果我想处理unicode字符,我应该使用wchar_t吗?
同样地,我怎么知道,如果一个特定的Unicode字符"支持"的wchar_t?
如果我有一个字符串:
std::string s = u8"??";
Run Code Online (Sandbox Code Playgroud)
在C ++ 20中
std::u8string s = u8"??";
Run Code Online (Sandbox Code Playgroud)
有何std::u8string不同std::string?
在¹comp.lang.c++ Usenet组中,我最近断言,基于我认为我所知道的,Windows的16位wchar_t,使用UTF-16编码,有时需要两个这样的值(称为"代理对")单个Unicode代码点,对于表示Unicode无效.
这肯定是不方便的,并且与C和C++标准库(例如字符分类)的假设相冲突,每个代码点都表示为单个值,尽管Unicode联盟的2004年"技术说明12"为使用UTF-16提供了一个很好的例子.用于内部处理,具有令人印象深刻的软件列表.
当然,似乎最初的意图是wchar_t每个代码点有一个值,与C和C++标准库的假设一致.例如,在ununix.org上的网页"ISO C修订1(MSE)"中,关于wchar_t1995年引入C标准的修订,作者坚持认为
"一个字节/一个字符模型的主要优点是,在固定宽度的块中处理数据非常容易.出于这个原因,人们发明了广泛性的概念.宽字符是一种抽象数据类型,其大小足以包含特定平台上支持的最大字符.
但事实证明,C和C++标准似乎并没有谈到支持的最大字符,而只讨论支持的语言环境中最大的扩展字符集:它必须足够大才能代表最大的扩展字符中的每个代码点当没有Unicode语言环境时,设置 - 但不是Unicode.wchar_t
" [
wchar_ttype]是一个整数类型,其值范围可以表示支持的语言环境中指定的最大扩展字符集的所有成员的不同代码.
这几乎与C++标准中的措辞完全相同.并且它似乎意味着使用受限制的一组受支持的语言环境,wchar_t确实可以很小,直到使用UTF-8编码的单个字节(例如,没有标准库字符分类功能在ASCII的A到Z之外工作的噩梦可能性,但是,嘿).可能以下要求比这更广泛:
"甲宽字符是类型的对象的代码值(二进制编码的整数)
wchar_t对应于扩展字符集的成员.
...因为它引用了扩展字符集,但该术语似乎无法在任何地方进一步定义.
至少在Microsoft的C和C++运行时,没有Unicode语言环境:该实现setlocale仅限于每个字符最多2个字节的字符编码:
setlocale:
"可用的区域设置名称,语言,国家/地区代码和代码页的集合包括Windows NLS API支持的所有内容,除了每个字符需要两个以上字节的代码页,例如UTF-7和UTF-8.如果您提供的代码页值为UTF-7或UTF-8,
setlocale则会失败,返回NULL.
所以它似乎与我认为的相反,与我的断言相反,Windows的16位wchar_t正式可以.主要是由于Microsoft巧妙地缺乏对UTF-8语言环境的支持,或者每个字符超过2个字节的任何语言环境.但它真的如此,16位wchar_t好吗?
链接:
¹消息:comp.lang.c ++
² http://unicode.org/notes/tn12/#Software_16
³ http://www.unix.org/version2/whatsnew/login_mse.html
⁴ https://开头MSDN. microsoft.com/en-us/library/x99tb11d.aspx
以下是我的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,在不实现的情况下,codecvt_utf8也不适用wchar_t.我不喜欢这种解释既得多,因为如果这是真的,也不char也不是wchar_t本地编码都是Unicode,似乎没有成为可移植的本地编码和Unicode之间进行转换的方式.
这两种解释中哪一种是正确的?还有另外一个我忽略了吗?
澄清我不是问关于wchar_t软件开发适用性的一般意见,或者wchar_t一个人的属性可以来自其他地方.我对标准的这两个特定段落感兴趣.我试图理解这些特定段落所包含或不包含的内容.
澄清2.如果4.1表示"facet将在UTF-8多字节序列和UCS2或UCS4之间进行转换,或者当前全局语言环境对wchar_t施加任何编码 ",则没有问题.它没有.它说的是什么.看起来如果使用std::codecvt_utf8<wchar_t>,最终会得到一堆wchar_t编码为UCS2或UCS4,而不管当前的全局语言环境.(无法指定区域设置或任何字符转换方面codecvt_utf8).所以这个问题可以这样改写:转换结果是否可以直接用于当前的全局语言环境(和/或任何可能的语言环境),用于输出,wctype查询等等?如果没有,它可用于什么?(如果上面的第二种解释是正确的,答案似乎是"没有").
C++ 中无前缀字符串的编码是什么?例如,所有字符串文字在 Java 中都被解析并存储为 UTF-16,在 Python3 中则被解析为 UTF-8。我猜想 C++ 文字就是这种情况u8""。但我不清楚像 之类的普通文字""。
以下代码的输出应该是什么?
#include <iostream>
#include <iomanip>
int main() {
auto c = "Hello, World!";
while(*c) {
std::cout << std::hex << (unsigned int){*c++} << " ";
}
}
Run Code Online (Sandbox Code Playgroud)
当我在我的机器上运行它时,它会给出以下输出:
48 65 6c 6c 6f 2c 20 57 6f 72 6c 64 21
Run Code Online (Sandbox Code Playgroud)
但这有保证吗?字符串文字的 Cppreference 页面表示普通字符串文字中的字符来自翻译字符集,翻译字符集指出:
翻译字符集由以下元素组成:
- 由 ISO/IEC 10646 命名的每个字符,由其唯一的 UCS 标量值标识,以及
- 每个 UCS 标量值的不同字符,其中未分配命名字符。
从这个定义来看,翻译字符集似乎是指 Unicode(或其超集)。那么除了显性之外,""和之间没有区别吗?u8""
假设如果我希望我的字符串采用 EBCDIC 编码(只是作为练习),那么在 …